提问人:One234Fi 提问时间:11/17/2023 更新时间:11/17/2023 访问量:92
为什么这个 for 循环的行为会根据它的编译方式而有所不同?
Why does this for loop behave differently depending on how it is compiled?
问:
我在编写基于 vulkan-tutorial 的方法时犯了一个错误,直到我更改了我的构建才发现该方法。如果您阅读以下内容,您将看到错误的方法以及更正的方法。错误本身不是我要问的,而是为了完整性:问题是我交换了决定循环长度的变量。出于某种原因,当通过 GCC 一步编译和链接程序时,该方法仍然返回 true,即使由于我的错误它应该返回 false。当我后来更改我的构建以单独将文件编译为对象,然后在后面的步骤中链接它们时,此方法返回了应有的 false。
问:为什么 for 循环在不同的构建中表现不同?
信息:
### "All in one" GCC command used:
gcc $(CFLAGS) -o $(BIN_DIR)/$(NAME) $(SRC_DIR)/\*.c $(LDFLAGS)
### commands used for the multi-step build:
compile step (run per-file):
gcc $(CFLAGS) -c -o $(SRC_DIR)/object1.c $(INCLUDES_FLAGS)
link step:
gcc $(CFLAGS) -o output $(objects) $(LDFLAGS)
Relevant flags used:
CFLAGS = -std=c17 -Wall -Wextra -Wno-unused-parameter -Werror=return-type -pthread -g -O0
LDFLAGS = -lc -lm -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi -lcglm
方法不正确(将硬编码常量LAYER_COUNT与运行时找到的 layerCount 交换):
const char* validationLayers[] = {
"VK_LAYER_KHRONOS_validation",
};
const uint32_t LAYER_COUNT = (sizeof(validationLayers) / sizeof(validationLayers[0]));
...
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
VkLayerProperties availableLayers[layerCount];
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
const char* layerName;
for (uint32_t i = 0; i < layerCount; i++) {
layerName = validationLayers[i];
bool layerFound = false;
VkLayerProperties layerProperties;
for (uint32_t j = 0; j < LAYER_COUNT; j++) {
layerProperties = availableLayers[j];
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}
更正方法:
const char* validationLayers[] = {
"VK_LAYER_KHRONOS_validation",
};
const uint32_t LAYER_COUNT = (sizeof(validationLayers) / sizeof(validationLayers[0]));
...
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
VkLayerProperties availableLayers[layerCount];
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
const char* layerName;
for (uint32_t i = 0; i < LAYER_COUNT; i++) {
layerName = validationLayers[i];
bool layerFound = false;
VkLayerProperties layerProperties;
for (uint32_t j = 0; j < layerCount; j++) {
layerProperties = availableLayers[j];
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}
我希望该方法在一个步骤中编译和链接时或作为单独的步骤进行编译和链接时具有一致的行为。我通过在全新安装下运行上述代码并获得相同的行为,确定这不是我的环境或 VulkanSDK 的问题。在这两种情况下,CFLAGS 和 LDFLAGS 变量也是相同的。
答: 暂无答案
评论
printf()