如何为 C 中声明之外的字符串赋值?巴士 error/segfault
How to assign a value to a string outside the declaration in C ? Bus error/segfault
我正在尝试重新编码一个 strstr()
函数的等价物,经过几次尝试我做对了,这里是代码:
(我知道有更简单的方法可以做到这一点,但这次我想尝试使用第三个字符串来存储事件)
char *my_strstr(char *s1, char *s2)
{
int i, j;
char *tmp;
i = (j = 0);
if (s1 != '[=11=]' && s2 != '[=11=]')
{
while (s1[i] != '[=11=]' && s2[j] != '[=11=]')
{
if (s1[i] == s2[j])
{
tmp[j] = s1[i];
j++;
}
i++;
}
printf("tmp = %s\n", tmp);
}
return (tmp);
}
int main()
{
char a[] = "test Point123";
char b[] = "Point123";
char *ret;
ret = my_strstr(a, b);
printf("ret = %s\n",ret);
return (0);
}
我得到了我想要的输出:
tmp = Point123
ret = Point123
但是为了确保我尝试了更长的字符串,这就是问题开始的地方。
这是我试过的字符串,
char a[] = "test Point123456789";
char b[] = "Point123456789";
以及我得到的输出:
tmp = Point123456?"1
ret = Point123456?"1
Abort trap: 6
对于较长的字符串,我有时会遇到段错误,有时会遇到总线错误 10。
在其他一些 post 上,我认为总线错误 10 有时会替换 mac OS 上的段错误(这是我第一次编码,我习惯于 linux), 我没有找到任何关于陷阱的信息。
无论如何,我发现它更多的是我的编译器的代码问题,我想知道为什么我的代码在较小的字符串上运行而不是在较大的字符串上运行,我读到这可能是我如何影响字符串的值我正在使用,但我不明白我哪里出错了。
因此,如果有人能告诉我我做错了什么,我将不胜感激:)
编辑
我按照评论里的建议做了,这是我修复后的功能,现在运行正常了,谢谢。
(同样,我知道我不需要 tmp,还有许多其他更简单、更快速的方法可以做到这一点——这意味着训练(显然我需要 ^^))
char *my_strstr(char *s1, char *s2)
{
int i, j;
char *tmp;
i = (j = 0);
tmp = malloc(sizeof(strlen(s2)));
if (s1 != '[=15=]' && s2 != '[=15=]')
{
while (s1[i] != '[=15=]' && s2[j] != '[=15=]')
{
if (s1[i] == s2[j])
{
tmp[j] = s1[i];
j++;
}
else
j = 0;
i++;
}
}
return (tmp);
}
您没有为 tmp
分配内存,因此对于 tmp[j]
,您正在写入某个未分配给您的随机内存位置。然后这个位置可能会被你所做的事情再次覆盖。
字符串越长,您弄乱的内存位置就越多。
你很幸运,你用较短的字符串得到了一些结果。
在您的代码中,tmp
是函数 my_strstr()
的自动局部变量。它没有被显式初始化,所以它包含不确定的值。
稍后在代码中,您将直接编写
tmp[j] = s1[i];
使用(取消引用)tmp
未初始化意味着您正在尝试访问无效的内存位置(还记得 "indeterministic value" 吗?),这可能不是从您的应用程序访问。它调用 undefined behaviour.
解决方案:您需要在访问(取消引用)之前为 tmp
分配内存。
编辑:
但是,根据下面的 from Mr. Vlad,您 my_strstr()
的逻辑也有问题。一旦您递增 j
( 搜索字符串的索引 )并发现两者之间不匹配,您就不会将其重新设置为 0
。也许您想再看一遍并更正。
我正在尝试重新编码一个 strstr()
函数的等价物,经过几次尝试我做对了,这里是代码:
(我知道有更简单的方法可以做到这一点,但这次我想尝试使用第三个字符串来存储事件)
char *my_strstr(char *s1, char *s2)
{
int i, j;
char *tmp;
i = (j = 0);
if (s1 != '[=11=]' && s2 != '[=11=]')
{
while (s1[i] != '[=11=]' && s2[j] != '[=11=]')
{
if (s1[i] == s2[j])
{
tmp[j] = s1[i];
j++;
}
i++;
}
printf("tmp = %s\n", tmp);
}
return (tmp);
}
int main()
{
char a[] = "test Point123";
char b[] = "Point123";
char *ret;
ret = my_strstr(a, b);
printf("ret = %s\n",ret);
return (0);
}
我得到了我想要的输出:
tmp = Point123
ret = Point123
但是为了确保我尝试了更长的字符串,这就是问题开始的地方。 这是我试过的字符串,
char a[] = "test Point123456789";
char b[] = "Point123456789";
以及我得到的输出:
tmp = Point123456?"1
ret = Point123456?"1
Abort trap: 6
对于较长的字符串,我有时会遇到段错误,有时会遇到总线错误 10。 在其他一些 post 上,我认为总线错误 10 有时会替换 mac OS 上的段错误(这是我第一次编码,我习惯于 linux), 我没有找到任何关于陷阱的信息。
无论如何,我发现它更多的是我的编译器的代码问题,我想知道为什么我的代码在较小的字符串上运行而不是在较大的字符串上运行,我读到这可能是我如何影响字符串的值我正在使用,但我不明白我哪里出错了。
因此,如果有人能告诉我我做错了什么,我将不胜感激:)
编辑
我按照评论里的建议做了,这是我修复后的功能,现在运行正常了,谢谢。
(同样,我知道我不需要 tmp,还有许多其他更简单、更快速的方法可以做到这一点——这意味着训练(显然我需要 ^^))
char *my_strstr(char *s1, char *s2)
{
int i, j;
char *tmp;
i = (j = 0);
tmp = malloc(sizeof(strlen(s2)));
if (s1 != '[=15=]' && s2 != '[=15=]')
{
while (s1[i] != '[=15=]' && s2[j] != '[=15=]')
{
if (s1[i] == s2[j])
{
tmp[j] = s1[i];
j++;
}
else
j = 0;
i++;
}
}
return (tmp);
}
您没有为 tmp
分配内存,因此对于 tmp[j]
,您正在写入某个未分配给您的随机内存位置。然后这个位置可能会被你所做的事情再次覆盖。
字符串越长,您弄乱的内存位置就越多。
你很幸运,你用较短的字符串得到了一些结果。
在您的代码中,tmp
是函数 my_strstr()
的自动局部变量。它没有被显式初始化,所以它包含不确定的值。
稍后在代码中,您将直接编写
tmp[j] = s1[i];
使用(取消引用)tmp
未初始化意味着您正在尝试访问无效的内存位置(还记得 "indeterministic value" 吗?),这可能不是从您的应用程序访问。它调用 undefined behaviour.
解决方案:您需要在访问(取消引用)之前为 tmp
分配内存。
编辑:
但是,根据下面的 my_strstr()
的逻辑也有问题。一旦您递增 j
( 搜索字符串的索引 )并发现两者之间不匹配,您就不会将其重新设置为 0
。也许您想再看一遍并更正。