2010-07-20 68 views
1

当您使用以下标志进行编译时,如果添加/ GF-或删除opimization标志,它们不会崩溃,下面的代码在VS 2010中崩溃。崩溃发生在汇编代码翻译'if(path [i] =='/')'。我喜欢理解编译器在这里做的优化,并导致崩溃。期待一些提示。VS2010 C代码 - 字符串池

-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

你说这崩溃了。有没有额外的信息说明它为什么崩溃?你展示的代码不应该有任何问题。正如你所说,条件应该阻止执行任务,因为在传递给函数的'path'中没有''/''字符。你确定你在这里展示的代码是你正在运行的代码的精确副本吗? – 2016-03-03 20:17:00

回答

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 
    } 
} 

字符串字面量通常存储在只读存储器中,这样您的实施,试图在访问冲突崩溃程序修改字符串文字的结果。

+0

感谢您的回复。我明白修改“字符串”字面意思会导致未指定的行为。但是我的观点是,当字符串文字因代码中的条件检查'path [i] =='/''而未被修改时,为什么优化的构建会导致崩溃。你能评论一下吗? – Kartlee 2010-07-22 16:09:36

+0

@Kartlee:当进行优化时,您无法确定在调试时哪一行,因此最可能的解释是您误解了调试会话的结果。确定修改if语句:if(path [i] =='/'){printf(“gonna modify \ n”);路径[i] ='\\'; }以便在修改尝试之前有一个调试打印。我很确定程序会在修改尝试后崩溃。 – sharptooth 2010-07-23 05:41:07

+0

但是在他显示的代码中,他传递给函数的'path'中没有'/ /'字符。所以无论是编译器中有一个非常奇怪的错误,还是他没有告诉我们的东西。 – 2016-03-03 20:18:43

7

试图修改​​的内容会调用未定义的行为。

从ISO C99(Section 6.4.5/6

它是unspeci音响ED这些阵列是否是不同的条件是它们的元素具有适当的值。 如果程序试图修改这样的阵列,该行为是理解过程音响定义

从ISO C++ - 98(Section 2.13.4/2

是否所有字符串文字是不同的(即,被存储在非重叠对象)是实现定义的。 尝试修改字符串文字的效果未定义。

在大多数实现(包括MSVC)上,这会导致应用程序崩溃。

+0

感谢您的回复。我明白修改“字符串”字面意思会导致未指定的行为。但是我的观点是,当字符串文字因代码中的条件检查'path [i] =='/''而未被修改时,为什么优化的构建会导致崩溃。你能评论一下吗? – Kartlee 2010-07-22 16:09:05

+0

@Kartlee:path [i] ='\\';试图修改字符串文字的内容,这会导致应用程序崩溃,并且行为是未定义的(未指定)。 :)条件检查就好了恕我直言。 – 2010-07-22 16:27:10

+0

当没有输入由于条件检查而修改它的代码的字符串文字将导致崩溃时,这真令人吃惊。你有没有机会看到汇编代码在这里发生了什么?如果关闭字符串池,它们不会导致崩溃。我怀疑编译器是否有任何前瞻来检查字符串文字是否在字符串池打开时被修改。 – Kartlee 2010-07-22 17:00:38

-1

我们有一个应用程序,在VC6.0中似乎有一个字符串池中的错误。两个不同的字符串似乎“汇集”为一个字符串,导致崩溃。 VS2010中不会发生这种崩溃。或者如果/ VS用于VS6.0而不是/ ZI。只是想知道VS6.0中的默认是使用字符串池而不是VS2010中的默认值。在这种情况下,字符串池错误仍然存​​在。如果有许多接近完全相同的字符串,我有(尚未被审查)的工作理论是在字符串池中未检测到散列冲突,从而消除了两个字符串中的一个。在查看两个几乎相似的字符串的指针时,这将在生成的ASM代码中可见。 在我们的例子中,我们没有修改VC6.0中的字符串,只是引用它们。

+0

如果您有新问题,请点击[问问题](http://stackoverflow.com/questions/ask)按钮。如果有助于提供上下文,请包含此问题的链接。 - [发表评论](/ review/low-quality-posts/10887694) – Oz123 2016-01-14 19:21:44

+0

我需要分享一个案例我们有一个庞大的客户群,超过12年以上使用VS6.0 C++,我看到两个应用程序实例到字符串池。我们使用 - >名称值创建对象。我们提供了一个“find_object(”String“)”API来按名称搜索对象。使用字符串池时,已经观察到两种情况,其中对象“StringA”和“StringB”都被创建并存在,但是因为字符串对象已经过优化,所以它与原始字符串不匹配,因此无法通过搜索找到对象“StringB”。生成的* .asm显示已优化的字符串。 TBD消毒所以我可以分享。 – 2018-01-25 22:43:21