snprintf 分段错误
snprintf segmentation fault
我正在尝试理解 C 中的字符指针。
基本上我正在做的是声明一个 char* 指针 main 并在另一个函数中通过引用传递并在那里进行修改。现在,我想在 main 中打印 char 的值,这给了我分段错误。但是,如果我在被调用函数中打印值,它会打印得很好。
此外,当我尝试在 main 中对 char 指针执行 snprintf 时,我再次遇到分段错误,但不是在被调用的函数中。
我搜索并尝试理解字符和指针,但无法对其进行调试。
下面是带注释的代码:
#include<stdio.h>
int main(void)
{
char *a;
int ret;
/* Below line gives Segmentation Fault. */
// snprintf(a,10,"%s","Hello");
/* Below line prints '(null)'.OK */
printf("Before Function Call: %s\n",a);
ret = func(&a);
/* Below line prints count of characters returned from func .OK */
printf("Characters written : %d\n",ret);
/* Below line gives Segmentation Fault. */
printf("After Function Call: %s\n",a);
return 1;
}
int func(char *b)
{
int ret = 0;
/* Below line prints blank. Why? Above it prints '(null)'*/
printf(" In func-> Before operation: %s\n",b);
ret = snprintf(b,10,"%s",", World");
/* Below line prints ' World'. OK */
printf(" In func-> After operation: %s\n",b);
return ret;
}
尝试这样定义 a
:
char a[10];
目前您正在将未初始化的指针传递给 snprintf,因此当 snprintf 写入它时会出现未定义的行为。
int func(char *b)
^requires char pointer
你传递的是
ret = func(&a);
^This is of type char **
让我们逐行分析函数。
char *a;
在这里你声明了一个目前指向任何地方的指针。
/* Below line gives Segmentation Fault. */
// snprintf(a,10,"%s","Hello");
当然可以。由于 a
指向 "nowhere" 或 "anywhere",这是未定义的行为。您应该首先通过一种或其他方式分配内存,然后让 a
指向那里。然后你就可以按照你的描述使用了。
ret = func(&a);
在这里,您将 a
的 地址 传递给 func()
- 可以。
/* Below line gives Segmentation Fault. */
printf("After Function Call: %s\n",a);
a
已更改,不再像上面那样是空指针,而是指向无法读取任何内容的目的地。又是未定义的行为。
return 1;
这意味着失败。更好 return 0
因为那将意味着成功。
int func(char *b)
停止。上面你将 &a
传递给了 func。由于 a
是 char *
,&a
将是 char **
。 B 但 func
接受 char *
。因此存在导致错误的差异。
/* Below line prints blank. Why? Above it prints '(null)'*/
printf(" In func-> Before operation: %s\n",b);
因为上面你打印了 a
,这里你打印了 b
也就是 &a
.
ret = snprintf(b,10,"%s",", World");
在这里你写点东西到 b
点,也就是 main()
的 a
。 a
是一个指针,在 32 位系统上大小为 4,在 64 位系统上大小为 8。并且不应滥用于存储字符串。
printf(" In func-> After operation: %s\n",b);
这是偶然;您再次出现未定义的行为,并且可能会干扰调用者的堆栈框架。
让我们稍微改进一下您的代码:
// prototype - make the function known to main() so that the right calling convention is used
int func(char *b);
int main(void)
{
char *a = malloc(100); // should be adjusted depending on the needs...
int ret;
/* Below line no longer gives Segmentation Fault now. */
snprintf(a,10,"%s","Hello");
printf("Before Function Call: %s\n",a);
ret = func(a);
/* Below line prints count of characters returned from func .OK */
printf("Characters written : %d\n",ret);
printf("After Function Call: %s\n",a);
free(a); // as we alloc'ed it...
return 0; // as we didn't notice anything going wrong...
}
int func(char *b)
{
int ret;
printf(" In func-> Before operation: %s\n",b);
// Here is the qustion: do we want to append or to overwrite?
char * b_append = b + strlen(b);
ret = snprintf(b_append,10,"%s",", World");
printf(" In func-> After operation: %s\n",b);
printf(" In func-> We appended %s\n",b_append);
return ret;
}
我正在尝试理解 C 中的字符指针。 基本上我正在做的是声明一个 char* 指针 main 并在另一个函数中通过引用传递并在那里进行修改。现在,我想在 main 中打印 char 的值,这给了我分段错误。但是,如果我在被调用函数中打印值,它会打印得很好。
此外,当我尝试在 main 中对 char 指针执行 snprintf 时,我再次遇到分段错误,但不是在被调用的函数中。
我搜索并尝试理解字符和指针,但无法对其进行调试。
下面是带注释的代码:
#include<stdio.h>
int main(void)
{
char *a;
int ret;
/* Below line gives Segmentation Fault. */
// snprintf(a,10,"%s","Hello");
/* Below line prints '(null)'.OK */
printf("Before Function Call: %s\n",a);
ret = func(&a);
/* Below line prints count of characters returned from func .OK */
printf("Characters written : %d\n",ret);
/* Below line gives Segmentation Fault. */
printf("After Function Call: %s\n",a);
return 1;
}
int func(char *b)
{
int ret = 0;
/* Below line prints blank. Why? Above it prints '(null)'*/
printf(" In func-> Before operation: %s\n",b);
ret = snprintf(b,10,"%s",", World");
/* Below line prints ' World'. OK */
printf(" In func-> After operation: %s\n",b);
return ret;
}
尝试这样定义 a
:
char a[10];
目前您正在将未初始化的指针传递给 snprintf,因此当 snprintf 写入它时会出现未定义的行为。
int func(char *b)
^requires char pointer
你传递的是
ret = func(&a);
^This is of type char **
让我们逐行分析函数。
char *a;
在这里你声明了一个目前指向任何地方的指针。
/* Below line gives Segmentation Fault. */
// snprintf(a,10,"%s","Hello");
当然可以。由于 a
指向 "nowhere" 或 "anywhere",这是未定义的行为。您应该首先通过一种或其他方式分配内存,然后让 a
指向那里。然后你就可以按照你的描述使用了。
ret = func(&a);
在这里,您将 a
的 地址 传递给 func()
- 可以。
/* Below line gives Segmentation Fault. */
printf("After Function Call: %s\n",a);
a
已更改,不再像上面那样是空指针,而是指向无法读取任何内容的目的地。又是未定义的行为。
return 1;
这意味着失败。更好 return 0
因为那将意味着成功。
int func(char *b)
停止。上面你将 &a
传递给了 func。由于 a
是 char *
,&a
将是 char **
。 B 但 func
接受 char *
。因此存在导致错误的差异。
/* Below line prints blank. Why? Above it prints '(null)'*/
printf(" In func-> Before operation: %s\n",b);
因为上面你打印了 a
,这里你打印了 b
也就是 &a
.
ret = snprintf(b,10,"%s",", World");
在这里你写点东西到 b
点,也就是 main()
的 a
。 a
是一个指针,在 32 位系统上大小为 4,在 64 位系统上大小为 8。并且不应滥用于存储字符串。
printf(" In func-> After operation: %s\n",b);
这是偶然;您再次出现未定义的行为,并且可能会干扰调用者的堆栈框架。
让我们稍微改进一下您的代码:
// prototype - make the function known to main() so that the right calling convention is used
int func(char *b);
int main(void)
{
char *a = malloc(100); // should be adjusted depending on the needs...
int ret;
/* Below line no longer gives Segmentation Fault now. */
snprintf(a,10,"%s","Hello");
printf("Before Function Call: %s\n",a);
ret = func(a);
/* Below line prints count of characters returned from func .OK */
printf("Characters written : %d\n",ret);
printf("After Function Call: %s\n",a);
free(a); // as we alloc'ed it...
return 0; // as we didn't notice anything going wrong...
}
int func(char *b)
{
int ret;
printf(" In func-> Before operation: %s\n",b);
// Here is the qustion: do we want to append or to overwrite?
char * b_append = b + strlen(b);
ret = snprintf(b_append,10,"%s",", World");
printf(" In func-> After operation: %s\n",b);
printf(" In func-> We appended %s\n",b_append);
return ret;
}