6

これは私のコードです:

#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)

誰か助けてくれませんか?

4

3 に答える 3

10

fnに十分なスペースがありません。それにstrcatすることにより、スタック割り当ての終わりをスタックに上書きします。したがって、セグメンテーション違反になります。

代わりに、次のことを試すことができます。

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" );

そして、あなたは間違いなく文字列のために十分なスペースを割り当てました。使い終わったら、忘れずに解放してください。

于 2012-12-16T12:19:03.403 に答える
5
char *fn = "~/lyrics/";

fn読み取り専用メモリ内の文字列を指す可能性があるため、fnへのポインタとして宣言する必要がありますconst char

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

次に、いくつかのエラーがあることがわかります。より良い解決策は次のとおりです。

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

MAX_SIZEこれは、のサイズ"~/lyrics/"、の最大長、argv[1]およびの長さの合計になります".txt"

于 2012-12-16T12:19:14.223 に答える
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);

...
于 2012-12-16T12:26:15.593 に答える