使用void指针的通用副本

时间:2013-09-19 14:04:53

标签: c pointers segmentation-fault void

我实现了一个通用的快速排序,现在我想从命令行接受数组。以下是一个应该将字符指针从数组argv复制到base的函数。我得到分段错误。当我传递两个整数的地址时,副本工作正常。

#include<stdio.h>

void copy(void *src, void *dest, int size)
{
    char *s, *d;
    int i;

    s = src;
    d = dest;

    for(i = 0; i < size; i++)
        d[i] = s[i];
}

int main(int argc, char *argv[])
{
    void *base;
    int i = 10;
    int j = 20;

    printf("%d, %d\n", i, j);
    copy(&i, &j, sizeof(int));
    printf("%d, %d\n", i, j);

    copy(argv, base, sizeof(char *));

    return 0;
}

输出

10, 20
10, 10
Segmentation fault (core dumped)

4 个答案:

答案 0 :(得分:2)

argv是一个指针数组。如果您只想复制指针,可以这样做:

 base = calloc( argc, sizeof(char *) );
 copy( argv, base, argc * sizeof(char *) );

现在你有指针数组argv的副本,但它仍然包含指向原始参数argv[i]的指针。 如果您还要创建argv[i]的副本,请不要使用copy(),但是:

 char **base = calloc( argc, sizeof(char *) );
 int  i;

 for( i=0; i<argc; i++ )
     base[i] = strdup( argv[i] );

但请记住:argv[0]是程序的名称,我敢打赌你不希望它成为数组的一部分。为了避免它:

 base = calloc( argc-1, sizeof(char *) );
 copy( argv+1, base, (argc-1) * sizeof(char *) );

 char **base = calloc( argc, sizeof(char *) );
 int  i;

 for( i=1; i<argc; i++ )
     base[i-1] = strdup( argv[i] );

答案 1 :(得分:1)

您正尝试将sizeof(char*)个字节复制到base所指向的位置。但是你没有为base分配任何内存,所以程序会调用未定义的行为。

答案 2 :(得分:0)

void *base = malloc(strlen(argv[0])+1);

然后

copy(argv[0], base, strlen(argv[0])+1);

最后

free(base);

sizeof(char*)将返回单个指针的大小,而不是整个路径

修改

void *base;
int i;

if (argc>0)
{
   base = malloc(argc+1);// we have enough pointers for copying args (+1 to null terminat it)

   for(i=0; i < argc; i++)
   {
      base[i] = malloc(strlen(argv[i])+1);
      copy(argv[i], base[i], strlen(argv[i])+1);
   }
   base[i] = NULL;
}

base将是一个包含所有参数的双指针

你可能会这样做 memset(...)memcopy(...) btw

答案 3 :(得分:-1)

Argv不是单指针,它是双指针

你应该这样做:

base = calloc(1, sizeof(char *));
copy(argv[1], base, sizeof(char *));

如果你真的想复制完整的argv,你必须更换 带有strlen(argv [0])的sizeof(char *)并且必须使用argv [0]的长度分配base。