使用以下标志编译时,VS 2010中的代码崩溃,如果添加/ GF-或删除opimization标志,则不会崩溃。崩溃发生在汇编代码中,该代码转换为'if(path [i] =='/')'。我喜欢理解编译器在这里做的优化并导致崩溃。期待一些指示。
-Karthik
cl.exe /MD /O2 test.c
//
Test.c
#include <stdio.h>
#include <string.h>
void testpath(char* path, int bufsiz)
{
int i;
printf("%p\n", path);
for( i=0; i < strlen(path); i++ ) {
if( path[i] == '/' ) {
path[i] = '\\';
}
}
}
int main()
{
const char* path = "testexport.prj";
char *path1 = "testexport.prj";
printf("%p\n", path);
printf("%p\n", path1);
testpath(path, 1024);
}
答案 0 :(得分:7)
尝试修改string literal
的内容会调用未定义的行为。
来自ISO C99(Section 6.4.5/6
)
如果这些数组的元素具有适当的值,则这些数组是否不同是不明确的。 如果程序试图修改此类数组,则行为未定义
来自ISO C ++ - 98(Section 2.13.4/2
)
是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。 尝试修改字符串文字的效果未定义。
在大多数实现(包括MSVC)上,这会导致应用程序崩溃。
答案 1 :(得分:5)
您尝试修改字符串文字,这是未定义的行为。
const char* path = "testexport.prj";
testpath(path, 1024);
// then later:
void testpath(char* path, int bufsiz)
{
int i;
for( i=0; i`<`strlen(path); i++ ) {
if( path[i] == '/' ) {
path[i] = '\\';// <<<<<< UB here
}
}
字符串文字通常存储在只读内存中,因此在您的实现中,尝试修改字符串文字会导致访问冲突,从而导致程序崩溃。
答案 2 :(得分:-1)
我们有一个应用程序,在VC6.0中似乎存在字符串池中的错误。两个不同的字符串出现在&#34; pool&#34;到一个字符串,导致崩溃。 VS2010中不会发生此崩溃。或者如果在VS6.0中使用/ Zi而不是/ ZI。只是想知道VS6.0中的默认值是使用字符串池而不是VS2010中的默认值。在这种情况下,字符串池错误可能仍然存在。如果有许多字符串几乎相同,我所拥有的工作理论(尚未审查)是在字符串池中未检测到哈希冲突,这消除了两个字符串中的一个。当查看两个几乎相似的字符串的指针时,这将在生成的ASM代码中可见。 在我们的例子中,我们不是在VC6.0中修改字符串,只是引用它们。