简体   繁体   English

为什么即使我可以访问内存也会出现分段错误(核心转储)?

[英]why do I get Segmentation fault (core dumped) even when I have access to the memory?

I understand that there are better implementations of this reverse string function, I even have made one better than this, but I just want to know why this isn't working.我知道这个反向字符串函数有更好的实现,我什至做了一个比这更好的实现,但我只想知道为什么这不起作用。

I have _strlen(char *) function that returns the length of a string.我有_strlen(char *)函数,它返回字符串的长度。

Here is my code:这是我的代码:

#include <stdio.h>
#include <stdlib.h>

void rev_string(char *s)
{    
        int length = _strlen(s);
        char *clone = s;
        char *tmp = malloc(length * sizeof(char));

        tmp += length;

        while (*clone)
        {
                *tmp = *clone;
                tmp--;
                clone++;
        }

        tmp += 1;

        //so if you print this and check it you can see the reversing was successful
        //but I couldnt assign it back to the main string;
        printf("TMP-->%s,s-->%s\n",tmp,s);
        
        //I have debugged the problem to be in the next while loop
        while (*tmp)
        {
                *s = *tmp;
                tmp ++;
                s++;
       }    
}

int main(void)
{
        char *str;
        str = "five";
        rev_string(str);
        printf("done");
        printf("%s\n",str);
        return (0);
}

I am trying to understand pointers in-depth and I don't really know much about them at this point so I really appreciate any answer.我正在尝试深入了解指针,但此时我对它们的了解并不多,因此我非常感谢您的回答。

Comment of @user3121023 completely correct. @user3121023 的评论完全正确。

but even if you do s = tmp that will not work because s it's just a copy.但即使你做 s = tmp 也行不通,因为 s 它只是一个副本。 Althoug your code can work if will pass **s尽管您的代码可以通过 **s 才能工作

void rev_string(char **s) void rev_string(char **s)

int length = _strlen(*s); int 长度 = _strlen(*s);

Replace whole last loop with *s = tmp用 *s = tmp 替换整个最后一个循环

This will work as you expected.这将按您的预期工作。 But never do this in real programs, it's bad solution.但是千万不要在真正的程序中这样做,这是一个糟糕的解决方案。

According to the documentation of string literal :根据字符串文字的文档:

String literals are not modifiable (and in fact may be placed in read-only memory such as .rodata).字符串文字是不可修改的(实际上可以放置在只读内存中,例如 .rodata)。 If a program attempts to modify the static array formed by a string literal, the behavior is undefined.如果程序尝试修改由字符串文字形成的静态数组,则行为未定义。

Example:例子:

char* p = "Hello";
p[1] = 'M'; // Undefined behavior
char a[] = "Hello";
a[1] = 'M'; // OK: a is not a string literal

So, this所以这

char *str = "five";

needs to be需要是

char str[] = "five";

to be modifiable.可修改。


This statement这个说法

tmp += length;

makes tmp to point to the memory one element after the allocated array.使tmp指向分配数组后一个元素的内存。

And, accessing it first time with并且,第一次访问它

*tmp = *clone;

is out-of-bounds access which is Undefined Behavior .是越界访问,即未定义行为

You can verify this with valgrind .您可以使用valgrind验证这一点。


You need to allocate one extra character to accommodate the null-character so the length would be:您需要分配一个额外的字符来容纳空字符,因此长度为:

const size_t length = strlen(s) + 1;

and, the allocation would be:并且,分配将是:

char* tmp = malloc(length * sizeof(*tmp));
//                          ^^^^^^^^^^^^
//                          sizeof to variable idiom

The allocated memory needs to be freed after use to avoid the memory leak.分配的内存需要在使用后释放,以避免内存泄漏。


Here's the working example ( live ):这是工作示例( live ):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void rev_string(char *s)
{
    const size_t length = strlen(s) + 1;
    char *clone = s;
    char *tmp = malloc(length * sizeof(*tmp));

    char *p = tmp + length - 1;
    *p = '\0';

    p--;

    while (*clone)
    {
        *p = *clone;
        p--;
        clone++;
    }

    ++p;

    printf("TMP: %s, s: %s\n", p, s);
    
    while (*p)
    {
        *s = *p;
        p++;
        s++;
    }

    free(tmp);
}

int main()
{
    char str[] = "five";
    rev_string(str);
    printf("%s\n",str);
    return (0);
}

Output:输出:

TMP: evif, s: five
evif

暂无
暂无

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

相关问题 为什么我出现分段错误(核心已转储)并且没有错误和警告? - Why do I get Segmentation Fault (core dumped) and no errors and warnings? 为什么会出现错误“分段错误(核心已转储)”? - Why do I get the error “Segmentation fault (core dumped)”? 为什么会出现“分段错误(核心已转储)” - Why do I get “Segmentation fault (core dumped)” 为什么我会收到“分段错误(核心转储)”? - Why do I get 'Segmentation fault (core dumped)'? 当我使用N = 1023而不是1024时,为什么在下面的程序中出现分段错误(内核已转储)? - Why do i get a segmentation fault (core dumped) in the program below when i use N=1023 instead of 1024? 当我不返回函数指针时,为什么会出现分段错误(内核已转储)? - Why am I getting Segmentation fault (core dumped) when I do not return a pointer of my function? 为什么在尝试填充结构时出现分段错误(核心已转储)或总线错误(核心已转储)? - Why am I getting Segmentation fault (core dumped) or bus error (core dumped) when trying to populate a struct? 为什么我在以下代码中出现分段错误(核心转储)? - Why i'm getting Segmentation fault (core dumped) in the following code? 为什么我收到分段错误(核心转储) - Why am I getting Segmentation Fault (Core dumped) 为什么我会遇到分段错误(核心转储)? - Why am I getting a segmentation fault (core dumped)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM