[英]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.