前に述べたように、あなたのコードは機能しません。
strcpy(target, tmp)
両方の機能で使用するとエラーが発生します。これを行うことにより、が指すメモリがほぼ確実にオーバーフローすることを理解する必要がありますtarget
。strlen(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);
}