【问题标题】:(NASM, C)Why would you need to malloc twice to create an array as shown here(NASM,C)为什么需要 malloc 两次来创建数组,如此处所示
【发布时间】:2016-03-10 11:31:10
【问题描述】:
char** names=(char**)malloc(count*sizeof(char*));
//while loop
names[count]=(char*)malloc(size+1);//why malloc again?

所以char** names=(char**)malloc(count*sizeof(char*)); 创建一个指向托管4 times count 字节的位置的指针,然后将指针位置存储到名称?

然后在while循环中,分配size+1字节长内存,并将其地址赋予names[count],是指names指向的位置?那么这里从第一个malloc创建的内存存储了第二个malloc创建的内存位置?并且内存指针的大小是 4 字节,以便我可以通过从内存位置开始移动到接下来的 4 个字节来访问每个 names[count]

如果我的想法是正确的,这两行 c 代码的这些 NASM 实现是否正确:

;char** names=(char**)malloc(count*sizeof(char*));
  mov eax, dword count
  ;lea ebx, [eax*4]
  imul ebx, eax, 4
  push ebx
  call _malloc
  mov names, eax
  add esp, 4

;names[count]=(char*)malloc(size+1);
  mov ebx, size
inc ebx
push ebx
call _malloc
add esp,4
mov ebx, names
mov ecx, dword count
mov [ebx+ecx*4], eax

同样,这两行代码是以下 c 代码的一部分,用于从文件中提取名称并对其进行排序:

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

int main(int argc, char *argv[])
{
  char path[]="names.txt";

  char szName[50];

  int count=0;

  int size=0;

  int x=0;
  int y=0;

  char* temp=0;
  int pos=0;

  FILE* file=fopen(path,"rt");

  if (file){

  while (!feof(file)){

  fscanf(file,"%50s",szName);
  count++;


  }

  }
  else{
       printf("Error opening file\n");
       return 1;
  }

  printf ("Count: %d\n",count);

  char** names=(char**)malloc(count*sizeof(char*));

  rewind(file);

  count=0;



  while (!feof(file)){

  fscanf(file,"%50s",szName);

  size=strlen(szName);

  names[count]=(char*)malloc(size+1);

  strcpy(names[count],szName);

  count++;


  }

  printf("Original file\n");

  for (x=0;x<count;x++){

  printf("Name %d:\t%s\n",x+1,names[x]);

  }


  for (x=0;x<count;x++){

  temp=names[x];
  pos=x;

  for (y=x;y<count;y++){

      if (strcmp(temp,names[y])>0){

      temp=names[y];
      pos=y;

      }    
  }

  temp=names[x];
  names[x]=names[pos];
  names[pos]=temp;    
  }

  printf("Sorted names\n");

  for (x=0;x<count;x++){

  printf("Name %d:\t%s\n",x+1,names[x]);

  }

  system("PAUSE");  
  return 0;
}

【问题讨论】:

  • 不要做names[count]=(char*)malloc(size+1);。这是越界访问。
  • 这是我的导师给出的工作代码的一部分。我会将代码发布在操作中。
  • 工作?它似乎发生起作用了。它被认为是危险的,所以不要执行代码!
  • 您的讲师正在教您编写糟糕的代码。想要一个具有两个间接级别的动态数组? char (*array)[y] = malloc(x * sizeof *array);... 想要三层间接? char (*array)[y][z] = malloc(x * sizeof *array);... 如您所见,不需要多个mallocs 来产生一个数组,实际上使用多个mallocs 是错误的。 数组是一个连续的内存块,在单个分配中,大多数函数都依赖于此。 使用多个mallocs 会严重破坏很多标准函数
  • 好吧我不会用,不过还是请大家帮我理解一下背后的逻辑吧。

标签: c arrays pointers malloc nasm


【解决方案1】:

您的教授正在创建一个字符串数组。编写的代码不必要地令人困惑,但这个想法是合理的。

这是一个希望不那么容易混淆的例子

// copy an existing string just like strdup()
char* stringDuplicate(const char* string) {
    size_t size = strlen(string) + 1; // 1 additional for `\0` terminator
    char* result = (char*)malloc(size * (sizeof(char)));
    strcpy(result, string);
    return result;
}

// copy an existing string array
char** stringArrayDuplicate(const char** stringArray, size_t size) {
    // Allocate an array which can hold size number of strings
    char** result = (char**)malloc(size * sizeof(char *));

    // For each string in stringArray, copy the string
    for (size_t i = 0; i < size; ++i) {
        result[i] = stringDuplicate(stringArray[i]);
    }

    return result;
}

【讨论】:

  • 我对这个答案的主要问题是对“字符串数组”的引用。不幸的是,这是一个重大问题,因为“字符串”的冲突定义妨碍正确理解 C 标准库的情况并不少见。 编辑:我也不喜欢显式的void * 强制转换,尤其是malloc 的返回值。
【解决方案2】:

所以char** names=(char**)malloc(count*sizeof(char*)); 创建了一个指向某个位置的指针 托管4 times count 字节,然后将指针位置存储到名称?

是的,如果您的环境中的 sizeof(char*)4

然后在while循环中,分配size+1字节长的内存,并将其地址分配给 names[count],指的是name指向的位置?

形式部分是正确的,但后者是错误的。 将地址提供给names 指向的位置前面的count 元素。

那么这里第一个malloc创建的内存存储了第二个malloc创建的内存位置?

是的,确实如此。

并且是内存指针4字节的大小,

这取决于环境。

这样我就可以通过从内存位置开始移动到接下来的 4 个字节来访问每个名称[count]?

是的,如果您的环境中的sizeof(char*)4

如果我的想法是正确的,这两行 c 代码的这些 NASM 实现是否正确:

如果int 在您的环境中是一个 32 位整数,我发现代码中没有错误。

【讨论】:

  • “给定地址以计算名称指向的位置前面的元素,超出范围。” count 在第二个循环,那么你什么时候建议count 会越界?
  • @Michael 我错了,我错过了count=0;。非常抱歉。
  • 所以第一个malloc分配了8个字节:00000000。然后分配了后两个4个字节,它们的地址存储在上面,如下所示:11112222,其中1111是前 4 字节内存的位置。
猜你喜欢
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
相关资源
最近更新 更多