分段故障 - strcat

时间:2012-12-16 12:18:02

标签: c segmentation-fault valgrind

这是我的代码:

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

void main(int arge, char *argv[])
{
    FILE *f1;
    char ch,*fn="~/lyrics/";
    strcat(fn,argv[1]);
    strcat(fn,".txt");
    if( (f1 = fopen(fn,"r"))==NULL )
    {
        printf("\nWrong filename\n%s not found",argv[1]);
        return;
    }
    while((ch=getw(f1))!=EOF)
    {
        printf("%c",ch);
    }
}

我使用gcc -g -o file file.c编译它,编译器没有给出任何错误消息。但是当我运行它时,我收到错误消息:

Segmentation fault (core dumped)
Bad permissions for mapped region at address 0x8048659 at 0x402C36B: strcat 
(in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) by 0x80484D6: main (lyrics.c:9)

有人可以帮助我吗?

3 个答案:

答案 0 :(得分:4)

fn中没有足够的空间。通过strcat'ing到它,你覆盖它的堆栈分配的结束并进入堆栈..因此分段错误。

您可以尝试以下方式:

char fn[255];
strcpy( fn, "~/lyrics/" );
strcat( fn, argv[1] );
strcat( fn, ".txt" );

您只需要确保整个路径和文件名可以容纳255个字符。

或者你可以这样做:

char* fn = NULL;
int argvLen = strlen( argv[1] );
fn = malloc( 9 + argvLen + 4 + 1 ); // Add 1 for null terminator.
strcpy( fn, "~/lyrics/" );
strcat( fn, argv[1] );
strcat( fn, ".txt" );

你确实为字符串分配了足够的空间。完成之后别忘了释放它!

答案 1 :(得分:4)

char *fn = "~/lyrics/";

由于fn可以指向只读内存中的字符串,因此您应该将fn声明为指向const char的指针。

const char *fn = "~/lyrics/";

然后你可以看到有一些错误。这是一个更好的解决方案:

char fn[MAX_SIZE] = "~/lyrics/";

此处MAX_SIZE应为"~/lyrics/"的大小,argv[1]的最大长度和".txt"的长度之和。

答案 2 :(得分:1)

这种方法不可移植。

如果使用glibc,您也可以调用asprintf(),只需分配尽可能多的内存。

#include <stdio.h>

...

char * pFn = NULL;

if (-1 == asprintf(&pFn, "~/lyrics/%s.txt", argv+1);
{
  perror("asprintf()");
}
else
{
  ... /* use pFn */
}

free(pFn);

...