1

私はUNIXC開発の初心者であり、少しの助けが必要です。私には次の2つの機能があります。

void edit_char(){

     int i;
     int length = strlen(expression);
     char *tmp = (char *) malloc((length+1)*sizeof(char));
     pom[0]='*';
     for(i=1;i<length+1;i++){
         tmp[i] = expression[i-1];
     }
     strcpy(expression,tmp);
     free((void *) tmp);
 }



 char *edit_char2(char *string){

     int i;
     int length = strlen(string);
     char *tmp = (char *) malloc((length+1)*sizeof(char));
     tmp[0]='/';
     for(i=1;i<length+1;i++){
         tmp[i] = string[i-1];
     }
     strcpy(string,tmp);
     free((void *) tmp);
     return string;
  }

edit_char()は、グローバル変数を編集しますchar *expression。先頭に記号「*」を付けます。2番目のedit_char2()はほとんど同じことを行いますが、グローバル変数を編集する代わりに、引数から文字列を編集します。

最初の関数は正常に機能します。問題は2番目の関数のtmp変数にあります。Mallocは、サイズが(length + 1)の空のchar配列を返しません。「xd\372 \ 267xd \ 372 \ 267\020」を返します。

何が原因でしょうか?

4

3 に答える 3

3

mallocは、新しく割り当てられたメモリへのポインタを返すだけです。これは「空」とは見なされません。それを「空にする」場合、つまり、メモをNULLで埋める場合は、手動で行う必要があります。たとえば、次のように手動で使用するcallocか、埋める必要があります。

編集:また、各文字列に文字を追加しているので、使用すべきではないと思います

newstring = malloc((strlen(string) + 1) * sizeof(char))

代わりに

newstring = malloc((strlen(string) + 2) * sizeof(char))

新しい文字と終了の両方にスペースを割り当てるため\0

EDIT2:これは、関数が機能しない/安全ではないことも意味します!あなたは両方を作ろうとしていて、おそらく最初に割り当てられたよりも1つ多くの文字を含んでいますstringexpression

于 2012-11-24T13:38:42.730 に答える
1
 tmp[0]='/';
 for(i=1;i<length+1;i++){
     tmp[i] = string[i-1];
 }

の末尾のヌル文字をコピーしていませんstring。これはstrcpy(string,tmp);

ループmemmoveの代わりにを使用してコピーを実行できることに注意してください。forまた、の戻り値のキャストはmalloc必須ではないため、避ける必要があることに注意してください。free引数のキャストも必要ありません。

于 2012-11-24T13:34:11.307 に答える
0

前に述べたように、あなたのコードは機能しません。

strcpy(target, tmp)両方の機能で使用するとエラーが発生します。これを行うことにより、が指すメモリがほぼ確実にオーバーフローすることを理解する必要がありますtargetstrlen(target + 1)targetが(target内のすべての文字と末尾のNULL)の配列を指しているだけの場合はtmp、メモリ配列がchar短すぎるコンテンツをコピーしていることになります。これを説明するために、次のようなループを実行します。

/* allocate two strings, containing copies
   of constant string "Hello World" */
local_string = strdup("Hello World");
expression = strdup("Hello World");
for (i = 0; i < 100; i++) {
    edit_char();
    edit_char2(local_string);
    printf("global_string after: [%s]\n", expression);
    printf("local_string after: [%s]\n", local_string);
}

ほとんどの場合、100回目の反復のずっと前に、プログラムの異常終了につながります。Debian Linux Squeezeでは、次の出力が得られます。

user@host$ ./a.out
global_string before: [Hello World]
local_string before: [Hello World]
global_string after: [*Hello World]
[...]
global_string after: [************Hello World]
local_string after: [////////////Hello World]
*** glibc detected *** ./a.out: double free or corruption (!prev): 0x00000000020e2050

あなたが望むものを達成するために、あなたはもう少しポインター魔法を使う必要があります。これが実際の例であり、コードの重複を制限する設計の改善があります。

出力

 user@host$ ./a.out
global_string before: [Hello World]
local_string before: [Hello World]
global_string after: [*Hello World]
local_string after: [/Hello World]

コード

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

char        *global_string;

void        add_one_leading_character(char leading, char **pointer_to_string)
{

    char    *new_string;
    char    *old_string;

    /* old_string will hold the content of
       pointer_to_string, for convenience */
    old_string = *pointer_to_string;
    /* allocate a new, empty string
       (= filled with NULLs) holding enough space
       for an additional character */
    new_string  = calloc(sizeof(*old_string), strlen(old_string) + 2);
    /* new_string now holds the leading character,
       followed by NULLs */
    new_string[0] = leading;
    /* concatenate the old_string to the new_string */
    strcat(new_string, old_string);
    /* make the pointer parameter points to the
       address of new_string */
    *pointer_to_string = new_string;
    /* free the memory pointed by old_string */
    free(old_string);
}

int        main(int ac, char **av)
{
    char   *local_string;

    /* allocate two strings, containing copies
       of constant string "Hello World" */
    local_string = strdup("Hello World");
    global_string = strdup("Hello World");
    printf("global_string before: [%s]\n", global_string);
    printf("local_string before: [%s]\n", local_string);
    /* add leading characters */
    add_one_leading_character('/', &local_string);
    add_one_leading_character('*', &global_string);
    printf("global_string after: [%s]\n", global_string);
    printf("local_string after: [%s]\n", local_string);
}
于 2012-11-24T16:20:32.300 に答える