Korrumpierte Zeiger innerhalb einer Struktur als Parameter einer Methode
-
Hallo alle zusammen,
ich habe ein Problem mit Pointern woran ich verzweifel.
Und zwar bekomme ich eine Exception wenn ich vkCreateGraphicsPipelines(...) aufrufe.
Nach ein wenig Debugging wurde mir klar, dass das Problem in der Methode InVulkanPipeline::CreateGraphicsPipelineCreateInfo liegt.
Nach dem ich mir einen Breakpoint an der Stelle pipelineInfo.pVertexInputState = &vertexInputInfo; gesetzt habe konnte ich mit dem Cursor über die Stelle const VkPipelineVertexInputStateCreateInfo& vertexInputInfo in der Methode :CreateGraphicsPipelineCreateInfo gehen und bekam so folgende Informationen:
sType VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO (19)
pNext 0x00
flags 0
vertexBindingDescriptionCount 1
pVertexBindingDescription {binding=3435973836 stride=3435973836 inputRate=-858993460}
vertexAttributeDescriptionCount 2
pVertexAttributeDescription {binding=3435973836 stride=3435973836 inputRate=-858993460}
Anhand der Informationen kann ich entnehmen, dass die beiden Pointer pVertexBindingDescription und pVertexAttributeDescription irgendwie ins nirgendwo zeigen.Ich habe keine Ahnung wieso das nicht funktioniert, wenn ich zum Beispiel einfach den Code aus der Methode InVulkanPipeline::CreatePipelineVertexInputStateCreateInfo
direkt an die Stelle kopiere wo der Methodenaufruf erfolgt funktioniert es.
Ich hoffe ihr könnt mir helfen, ich glaube es ist irgendwas mit den Zeigern und Referenzen.
Ich weiß einfach nicht mehr weiter und hoffe, dass ihr mir helfen könnt.
Ich habe den Code angehängt.Gruß Pixma
Header Datei ///////////////////// class InVulkanPipeline { private: ... VkGraphicsPipelineCreateInfo CreateGraphicsPipelineCreateInfo( const VkPipelineShaderStageCreateInfo shaderStages[], const VkPipelineVertexInputStateCreateInfo& vertexInputInfo, const VkPipelineInputAssemblyStateCreateInfo& inputAssembly, const VkPipelineViewportStateCreateInfo& viewportState, const VkPipelineRasterizationStateCreateInfo& rasterizer, const VkPipelineMultisampleStateCreateInfo& multisampling, const VkPipelineColorBlendStateCreateInfo& colorBlending) const noexcept; VkPipelineVertexInputStateCreateInfo CreatePipelineVertexInputStateCreateInfo(VertexSource vertexSource) const noexcept; public: void CreateGraphicsPipeline(VkDevice logicalDevice, std::vector<ShaderPipeline> *shaderPipeline, VkPipelineLayout *pipelineLayout); }; Cpp Datei ///////////////////// void InVulkanPipeline::CreateGraphicsPipeline(VkDevice logicalDevice, std::vector<ShaderPipeline> *shaderPipeline, VkPipelineLayout *pipelineLayout) { ... VkPipelineVertexInputStateCreateInfo vertexInputInfo = CreatePipelineVertexInputStateCreateInfo(shaderPipeline->at(i).vertexSource); ... VkGraphicsPipelineCreateInfo pipelineInfo = CreateGraphicsPipelineCreateInfo(shaderStageInfo.data(), vertexInputInfo, inputAssembly, viewportState, rasterizer, multisampling, colorBlending); result = vkCreateGraphicsPipelines(logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &(shaderPipeline->at(i).pipeline)); if (result != VK_SUCCESS) { throw VulkanException(result, "Failed to create pipeline layout:"); } } VkPipelineVertexInputStateCreateInfo InVulkanPipeline::CreatePipelineVertexInputStateCreateInfo(VertexSource vertexSource) const noexcept { auto bindingDescription = Vertex::getBindingDescription(); auto attributeDescriptions = Vertex::getAttributeDescriptions(); VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; if (vertexSource == IN_VERTEX_SOURCE_STRUCT) { vertexInputInfo.vertexBindingDescriptionCount = 1; vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size(); vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); } else if(vertexSource == IN_VERTEX_SOURCE_SHADER) { vertexInputInfo.vertexBindingDescriptionCount = 0; vertexInputInfo.vertexAttributeDescriptionCount = 0; } else { // TODO IMPLEMENTEXCEPTION } return vertexInputInfo; } VkGraphicsPipelineCreateInfo InVulkanPipeline::CreateGraphicsPipelineCreateInfo( const VkPipelineShaderStageCreateInfo shaderStages[], const VkPipelineVertexInputStateCreateInfo& vertexInputInfo, const VkPipelineInputAssemblyStateCreateInfo& inputAssembly, const VkPipelineViewportStateCreateInfo& viewportState, const VkPipelineRasterizationStateCreateInfo& rasterizer, const VkPipelineMultisampleStateCreateInfo& multisampling, const VkPipelineColorBlendStateCreateInfo& colorBlending) const noexcept { VkGraphicsPipelineCreateInfo pipelineInfo = {}; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.stageCount = 2; pipelineInfo.pStages = shaderStages; pipelineInfo.pVertexInputState = &vertexInputInfo; pipelineInfo.pInputAssemblyState = &inputAssembly; pipelineInfo.pViewportState = &viewportState; pipelineInfo.pRasterizationState = &rasterizer; pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.layout = m_pipelineLayout; pipelineInfo.renderPass = m_renderPass; pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; return pipelineInfo; }
-
Zeiger auf temporäre Objekte in einer Datenstruktur zu speichern, die möglicherweise den Scope des temporären Objekts überlebt ist generell einer schlechte Idee.
Das ist einmal bei
vertexInputInfo
der Fall (Zeilen 29, 34, 83) und sehr warscheinlich auch beibindingDescription
/attributeDescriptions
(Zeilen 44, 45, 54, 55),
wobei man sich wegen demauto
nicht so ganz sicher sein kann.Letzteres ist ziemlich sicher auch die direkte Ursache für dein Problem:
Bedenke, dass die ObjektebindingDescription
undattributeDescriptions
als automatische Objekte (hat nix mit demauto
zu tun!) hier nur innerhalb von
CreatePipelineVertexInputStateCreateInfo()
existieren,vertexInputInfo
aber immer noch einen Zeiger auf diese hält, über den den Vulkan wahrscheinlich in
vkCreateGraphicsPipelines()
auf die Objekte zugreifen möchte. Dass diese Pointer zu dem Zeitpunkt auf Müll zeigen, ist daher nicht verwunderlich.Dasselbe Anti-Pattern wird dir wahrscheinlich auch mit
vertexInputInfo
zu einem späteren Zeitpunkt auf die Füße fallen.Tip: Da diese Beschreibungs-Strukturen konzeptionell zu dem gehören, was die Pipeline ausmacht, macht es Sinn, diese auch als Member von
InVulkanPipeline
zu speichern. Das hätte den Vorteil, dass die Zeiger darauf so lange gültig bleiben, wie das Pipeline-Objekt existiert.
-
Hallo Finnegan,
danke für deinen Hinweis. Das wusste ich noch garnicht, aber das macht Sinn.
Also wenn ich das richtig verstehe wird der Kontext gelöscht am Ende der Methode und die beiden Zuweisungen
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions(); sind dann unbekannt, oder?
Dies ist auch der Grund weshalb der Zeiger irgendwo ins Nirwana zeigt. Einfach weil die Variablen zerstört wurden.Ich habe jetzt einfach als Lösungsweg die beiden auto Variablen in die Klassendeklaration als Member Variablen hinzugefügt.
Aktuell läuft es, aber ich werde den Code dann die Tage noch mal refactoren, damit mir in der Zukunft nicht die vertexInputInfo um die Ohren fliegt.
Jedoch muss ich da dann noch mehr auslagern, weil ich für mehrere Strukturen aktuell diesen Weg gewählt hab.Vielen Dank,
das hat mir sehr geholfenGruß Pixma
-
Pixma schrieb:
Das wusste ich noch garnicht, aber das macht Sinn.
Also wenn ich das richtig verstehe wird der Kontext gelöscht am Ende der Methode und die beiden Zuweisungen
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions(); sind dann unbekannt, oder?So ist es.
Das ist allerdings elementares C++-Grundwissen, wenn du das also tatsächlich "nicht wusstest" und nicht nur "nicht erkannt" hast
(ist nicht immer leicht auf den ersten Blick zu erkennen), kannst du dir eine Menge ziemlich garantierten Ärger ersparen, wenn du
deine C++-Grundlagen nochmal etwas auffrischst, bevor du dich an ein komplexeres Programm wie dieses wagst - das ist immerhin
nur einer der harmloseren Fallstricke, die C++ zu bieten hat (bitte als gut gemeinten Rat auffassen ;)).