简体   繁体   English

反向字符串是seg faulting

[英]reverse a string is seg faulting

I've written a "reverse string" exercise as a preparation for my upcoming interviews, however, when I try to run the test on several items of my array, I am getting a segfault. 我写了一个“反向字符串”练习作为我即将进行的采访的准备,然而,当我尝试对我的阵列的几个项目进行测试时,我得到了一个段错误。

Basically if I compile the code below with -DWORKS, cstr with the string "zip it shrimp" is reversed as expected. 基本上如果我使用-DWORKS编译下面的代码,带有字符串“zip it shrimp”的cstr将按预期反转。 However, if I leave it will compile the code that uses the array of pointers but fails on the first iteration (ie cstr[i] where i = 0): 但是,如果我离开它将编译使用指针数组但在第一次迭代时失败的代码(即cstr [i],其中i = 0):

*s = *e;

I seem to recall that we can't change a pointer directly, but I can't seem to think of a way to work around this. 我似乎记得我们不能直接改变指针,但我似乎无法想办法解决这个问题。 Any help understanding what exactly is leading to the fault and how I can fix it and understand this better so I don't repeat it again, would be greatly appreciated. 任何帮助,了解究竟是什么导致了错误,以及如何更好地解决它并更好地理解它,所以我不再重复它,将不胜感激。 Whole code below. 整个代码如下。

#include <stdio.h>

char *str[] = { "zip it shrimp", "", "a", "ab", "abc" };
char cstr[] = "zip it shrimp";

void reverse(char *str)
{       
        char *s = str;
        char *e = s + strlen(s) - 1;

        while (s < e) {
                char c = *s;
                *s = *e;
                *e = c;
                s++;
                e--;
        }
}

int main(int argc, char **argv)
{
        int i;
#ifdef WORKS
        reverse(&cstr);
        printf("%s\n", cstr);
#else
        for (i = 0; i < 4; i++) {
                reverse(str[i]);
                printf("%s\n", str[i]);
        }
#endif
        return 0; 
}       

When reverse the array of pointers, you are modifying the string literals, which is undefined behaviour . 当反转指针数组时,您正在修改字符串文字,这是未定义的行为 You can't modify any of strings in: 您无法修改以下任何字符串:

char *str[] = { "zip it shrimp", "", "a", "ab", "abc" };

Copy the strings into a modifiable memory locations and then reverse them. 将字符串复制到可修改的内存位置,然后将其反转。 One way is to use strdup() . 一种方法是使用strdup()

  for (i = 0; i < 4; i++) { 
            char *p=strdup(str[i]);
            if (!p) { /* handle error */ }
            reverse(p);
            printf("%s\n", p);
            free(p);
    }

If you simply want to print them in reverse, you can print them without doing any copy at all. 如果您只是想反向打印它们,您可以打印它们而不进行任何复制。 But that depends on how you want implement it. 但这取决于你想要如何实现它。

If you don't explicitly reserve mutable space for string literals (section 6.4.5 in the language spec) as you do for cstr , they are not guaranteed to be assigned mutable storage. 如果没有为cstr明确保留字符串文字的可变空间(语言规范中的第6.4.5节),则不能保证它们被分配给可变存储。

See also Is modification of string literals undefined behaviour according to the C89 standard? 另请参阅根据C89标准修改字符串文字的未定义行为? .

C11, draft spec N1516, section 6.4.5.7 states: C11,规范草案N1516,第6.4.5.7节规定:

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. 如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。 If the program attempts to modify such an array, the behavior is undefined. 如果程序试图修改此类数组,则行为未定义。

C99, draft spec WG14/N1256, section 6.4.5.6 states: C99,规范草案WG14 / N1256,第6.4.5.6节规定:

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. 如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。 If the program attempts to modify such an array, the behavior is undefined. 如果程序试图修改此类数组,则行为未定义。

The compiler is free to take such literals and merge them with literals of other modules. 编译器可以自由地使用这些文字并将它们与其他模块的文字合并。 If you were to allow modifications of such strings, you might affect string literals from other moduls. 如果您允许修改此类字符串,则可能会影响其他模块的字符串文字。 In Linux, such literals are stored in .rodata sections (read-only data) and the loader will ensure that they are not writeable-- which leads to the segmentation fault that you are observing. 在Linux中,这样的文字存储在.rodata部分(只读数据)中,加载器将确保它们不可写 - 这会导致您正在观察的分段错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM