c 指针到指针的内存分配

发布于 2024-10-04 06:38:42 字数 2623 浏览 6 评论 0原文

我是一个 c 菜鸟,我的这段代码无法正常工作,因为我为 char** 指针做了一些错误的内存分配。你能帮忙吗?提前谢谢很多。 代码:

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



struct node_t {

 struct tuple_t *tuple; //Entrada na lista

 struct node_t *next; //o node seguinte da lista

};

struct tuple_t {
 long timestamp; /* instante de criacao do tuplo*/
 int n_fields; /* numero de campos deste tuplo */
 char **fields; /* array com campos do tuplo */
 /* 4 + 4 + 4  bytes?? */
};

char ** split_str(char [], char **, const char *);

struct node_t *node_create(void *node_data){

 struct node_t *node = NULL;
 node = (struct node_t *)malloc(sizeof(struct node_t));
 if(!node){
  printf("Erro ao criar um node!\n");
  return NULL;
 }

 node->tuple = (struct tuple_t *)malloc(sizeof(struct tuple_t));
 if(!node->tuple){printf("Erro ao criar o node->tuple\n"); free(node); return NULL;}

 node->tuple->fields = (char ** )malloc(strlen((char *) node_data) * sizeof(char *));
 if(!node->tuple->fields){ printf("Erro ao criar o node->tuple->node_fields\n"); free(node->tuple); free(node); return NULL; }

 char **array;
 const char *sep=" ";
 char *s = (char *)node_data;
 char arr[strlen(s)];
 int i = 0;
 while(arr[i++]=s[i]);

 array = split_str(arr,array, sep); 

 i = 0;
 while(array[i]){
  node->tuple->fields[i] = (char *)malloc((strlen(array[i])) * sizeof(char));
  if(!node->tuple->fields[i]){
   printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
   return NULL;
  }
  node->tuple->fields[i] = array[i];
//  printf("array[i]=%s\n",array[i]);
//  printf("node->tuple->fields[i]=%s\n",node->tuple->fields[i]);
  i++;

 }

 node->tuple->n_fields = i;
 node->tuple->timestamp = 0L;
 node->next = NULL;

 return node;
}

char** split_str(char writablestring[],char **array, const char *sep ){

 array = malloc(strlen(writablestring) + 1);

 if(! array){printf("Erro ao alocar memoria para o array em split\n"); return NULL;}

 char *token = strtok(writablestring, sep);

 int i=0;
 while(token != NULL)
 {
  array[i] = malloc(strlen(token)+1);
  if(!array[i])
   return NULL;
  array[i] = token;
  token = strtok(NULL, " ");
  i++;
 }

 return array;
}


int main(int argc, char** argv)
{

 void * n_data = "hello 123 ploc";

 struct node_t * node = node_create(n_data);
 printf("node->num_fields=%d\n", node->tuple->n_fields);
 int i=0;

 while( node->tuple->fields[i] ){
  printf("node->tuple->fields[%d]=%s\n",i,node->tuple->fields[i]);
  i++;
 }

 return 0;
}

结束代码。

I am a noob in c, and i have this code that doesnt work properly because some bad memory allcoation i make for a char** pointer. Could you please help? Thx a lot in advance.
Code:

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



struct node_t {

 struct tuple_t *tuple; //Entrada na lista

 struct node_t *next; //o node seguinte da lista

};

struct tuple_t {
 long timestamp; /* instante de criacao do tuplo*/
 int n_fields; /* numero de campos deste tuplo */
 char **fields; /* array com campos do tuplo */
 /* 4 + 4 + 4  bytes?? */
};

char ** split_str(char [], char **, const char *);

struct node_t *node_create(void *node_data){

 struct node_t *node = NULL;
 node = (struct node_t *)malloc(sizeof(struct node_t));
 if(!node){
  printf("Erro ao criar um node!\n");
  return NULL;
 }

 node->tuple = (struct tuple_t *)malloc(sizeof(struct tuple_t));
 if(!node->tuple){printf("Erro ao criar o node->tuple\n"); free(node); return NULL;}

 node->tuple->fields = (char ** )malloc(strlen((char *) node_data) * sizeof(char *));
 if(!node->tuple->fields){ printf("Erro ao criar o node->tuple->node_fields\n"); free(node->tuple); free(node); return NULL; }

 char **array;
 const char *sep=" ";
 char *s = (char *)node_data;
 char arr[strlen(s)];
 int i = 0;
 while(arr[i++]=s[i]);

 array = split_str(arr,array, sep); 

 i = 0;
 while(array[i]){
  node->tuple->fields[i] = (char *)malloc((strlen(array[i])) * sizeof(char));
  if(!node->tuple->fields[i]){
   printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
   return NULL;
  }
  node->tuple->fields[i] = array[i];
//  printf("array[i]=%s\n",array[i]);
//  printf("node->tuple->fields[i]=%s\n",node->tuple->fields[i]);
  i++;

 }

 node->tuple->n_fields = i;
 node->tuple->timestamp = 0L;
 node->next = NULL;

 return node;
}

char** split_str(char writablestring[],char **array, const char *sep ){

 array = malloc(strlen(writablestring) + 1);

 if(! array){printf("Erro ao alocar memoria para o array em split\n"); return NULL;}

 char *token = strtok(writablestring, sep);

 int i=0;
 while(token != NULL)
 {
  array[i] = malloc(strlen(token)+1);
  if(!array[i])
   return NULL;
  array[i] = token;
  token = strtok(NULL, " ");
  i++;
 }

 return array;
}


int main(int argc, char** argv)
{

 void * n_data = "hello 123 ploc";

 struct node_t * node = node_create(n_data);
 printf("node->num_fields=%d\n", node->tuple->n_fields);
 int i=0;

 while( node->tuple->fields[i] ){
  printf("node->tuple->fields[%d]=%s\n",i,node->tuple->fields[i]);
  i++;
 }

 return 0;
}

End code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哆兒滾 2024-10-11 06:38:42

您的 split_str() 函数返回指向 writablestring 的指针,它是 node_create() 中的数组 arr。然后,您将这些指针复制到 node->tuple->fields[i] 中 - 但 arr 数组在 node_create()< 之后将不存在/code> 函数退出 - 因此这些指针将不再有效。相反,您需要将返回的字符串复制到您分配的内存中(这也展示了如何使用 for() 循环代替 while(),并且您还需要释放在 split_str() 中分配的内存):

for (i = 0; array[i]; i++) {
    node->tuple->fields[i] = malloc(strlen(array[i]) + 1);

    if (!node->tuple->fields[i]){
        printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
        return NULL;
    }

    strcpy(node->tuple->fields[i], array[i]);
}

free(array);

此外,您的代码假定 split_str() 返回的数组code> 将由 NULL 终止,但该函数不能确保这一点。该函数还有许多其他问题(传递给 malloc() 的大小不正确、不必要的 malloc() 导致的内存泄漏) - 因此您也需要修复它:(

char **split_str(char writablestring[], const char *sep)
{
    char **array = malloc(strlen(writablestring) * sizeof array[0]);

    if(!array) {
        printf("Erro ao alocar memoria para o array em split\n");
        return NULL;
    }

    char *token = strtok(writablestring, sep);
    int i;

    for (i = 0; (array[i] = token) != NULL; i++) {
        token = strtok(NULL, " ");
    }

    return array;
}

注意该 array 不需要作为参数传递 - 它会立即被覆盖,所以我把它变成了一个局部变量)。


完成此操作后,您可能会注意到实际上没有理由在 split_str() 中分配 array,而只是将其内容复制到 node->; tuple->fields 然后释放它。您也可以将数组 node->tuple->fields 传递给 split_str() 并让它直接写入其中。然后它可以返回分配的字符串数量 - 如下所示:

int split_str(char [], char **, const char *);

struct node_t *node_create(void *node_data)
{
    struct node_t *node = NULL;
    char *s = node_data;
    size_t slen = strlen(s);

    node = malloc(sizeof *node);
    if (!node) {
        printf("Erro ao criar um node!\n");
        return NULL;
    }

    node->tuple = malloc(sizeof *node->tuple);
    if (!node->tuple) {
        printf("Erro ao criar o node->tuple\n");
        free(node);
        return NULL;
    }

    node->tuple->fields = malloc(slen * sizeof node->tuple->fields[0]);
    if (!node->tuple->fields) {
        printf("Erro ao criar o node->tuple->node_fields\n");
        free(node->tuple);
        free(node);
        return NULL;
    }

    char arr[slen + 1];
    strcpy(arr, s);

    int i = split_str(arr, node->tuple->fields, " ");

    node->tuple->n_fields = i;
    node->tuple->timestamp = 0L;
    node->next = NULL;

    return node;
}

int split_str(char writablestring[], char **array, const char *sep)
{
    char *token = strtok(writablestring, sep);
    int i;

    for (i = 0; token != NULL; i++) {
        array[i] = malloc(strlen(token) + 1);
        if (!array[i]) {
            printf("Erro ao criar o array[i]\n");
            break;
        }
        strcpy(array[i], token);
        token = strtok(NULL, " ");
    }

    return i;
}

Your split_str() function returns pointers into writablestring, which is the array arr in node_create(). You then copy these pointers into node->tuple->fields[i] - but the arr array won't exist after the node_create() function exits - so those pointers will no longer be valid. Instead, you need to copy the returned string into the memory that you have allocated (this also shows how you can use a for() loop in place of your while(), and you also need to free the memory that was allocated in split_str()):

for (i = 0; array[i]; i++) {
    node->tuple->fields[i] = malloc(strlen(array[i]) + 1);

    if (!node->tuple->fields[i]){
        printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
        return NULL;
    }

    strcpy(node->tuple->fields[i], array[i]);
}

free(array);

Additionally, your code assumes that the array returned by split_str() will be terminated by a NULL, but the function does not ensure this. The function has numerous other problems (incorrect size passed to malloc(), memory leak caused by unnecessary malloc()) - so you need to fix it, too:

char **split_str(char writablestring[], const char *sep)
{
    char **array = malloc(strlen(writablestring) * sizeof array[0]);

    if(!array) {
        printf("Erro ao alocar memoria para o array em split\n");
        return NULL;
    }

    char *token = strtok(writablestring, sep);
    int i;

    for (i = 0; (array[i] = token) != NULL; i++) {
        token = strtok(NULL, " ");
    }

    return array;
}

(Note that array does not need to be passed as a parameter - it's being immediately overwritten anyway, so I turned it into a local variable).


Once you've done this, you might notice that there's really no reason to allocate array in split_str(), only to copy its contents to node->tuple->fields and then free it. You might as well pass the array node->tuple->fields to split_str() and have it write directly into it. It could then return the number of strings allocated - that would look like:

int split_str(char [], char **, const char *);

struct node_t *node_create(void *node_data)
{
    struct node_t *node = NULL;
    char *s = node_data;
    size_t slen = strlen(s);

    node = malloc(sizeof *node);
    if (!node) {
        printf("Erro ao criar um node!\n");
        return NULL;
    }

    node->tuple = malloc(sizeof *node->tuple);
    if (!node->tuple) {
        printf("Erro ao criar o node->tuple\n");
        free(node);
        return NULL;
    }

    node->tuple->fields = malloc(slen * sizeof node->tuple->fields[0]);
    if (!node->tuple->fields) {
        printf("Erro ao criar o node->tuple->node_fields\n");
        free(node->tuple);
        free(node);
        return NULL;
    }

    char arr[slen + 1];
    strcpy(arr, s);

    int i = split_str(arr, node->tuple->fields, " ");

    node->tuple->n_fields = i;
    node->tuple->timestamp = 0L;
    node->next = NULL;

    return node;
}

int split_str(char writablestring[], char **array, const char *sep)
{
    char *token = strtok(writablestring, sep);
    int i;

    for (i = 0; token != NULL; i++) {
        array[i] = malloc(strlen(token) + 1);
        if (!array[i]) {
            printf("Erro ao criar o array[i]\n");
            break;
        }
        strcpy(array[i], token);
        token = strtok(NULL, " ");
    }

    return i;
}
胡渣熟男 2024-10-11 06:38:42

尝试这样的事情:

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


struct tuple_t
{ 
    long timestamp; /* instante de criacao do tuplo*/ 
    int n_fields; /* numero de campos deste tuplo */ 
    char** fields; /* array com campos do tuplo */ 
}; 

struct node_t
{ 
    struct tuple_t* tuple; //Entrada na lista 
    struct node_t* next; //o node seguinte da lista 
}; 


char** split_str(const char *, const char *, int *); 
void node_destroy(struct node_t*);

struct node_t* node_create(char* node_data)
{ 
    struct node_t* node = (struct node_t *) malloc(sizeof(struct node_t)); 
    if(!node)
    { 
        printf("Erro ao criar um node!\n"); 
        return NULL; 
    } 

    node->tuple = (struct tuple_t *) malloc(sizeof(struct tuple_t));
    if(!node->tuple)
    {
        printf("Erro ao criar o node->tuple\n");
        node_destroy(node);
        return NULL;
    } 

    node->tuple->timestamp = 0L; 

    node->tuple->fields = split_str(node_data, " ", &(node->tuple->n_fields));
    if(!node->tuple->fields)
    {
        printf("Erro ao criar o node->tuple->node_fields\n");
        node_destroy(node);
        return NULL;
    } 

    node->next = NULL; 

    return node; 
} 

void node_destroy(struct node_t* node)
{
    if(node)
    {
        if(node->tuple)
        {
            if(node->tuple->fields)
            {
                for(int i = 0; i < node->tuple->n_fields; ++i)
                    free(node->tuple->fields[i]);

                free(node->tuple->fields);
            }

            free(node->tuple);
        }

        free(node);
    }
}

char** split_str(const char* str, const char* sep, int* found)
{ 
    if (found) *found = 0;

    int len = strlen(str);

    char** array = (char**) malloc(len * sizeof(char*));
    if(!array)
    {
        printf("Erro ao alocar memoria para o array em split\n");
        return NULL;
    }

    ++len;

    char* writablestring = (char*) malloc(len); 
    if(!array)
    {
        printf("Erro ao alocar memoria para writeablestring em split\n");
        free(array);
        return -1;
    } 

    strncpy(writablestring, str, len);

    char* token = strtok(writablestring, sep); 
    int i = 0;

    while(token)
    { 
        len = strlen(token) + 1;

        array[i] = (char*) malloc(len);
        if(!array[i]) 
        {
            printf("Erro ao alocar memoria para o array item em split\n");

            free(writeablestring);
            for(int j = 0; j < i; ++j)
                free(array[j]);
            free(array);
            return NULL;
        }

        strncpy(array[i], token, len); 
        ++i;

        token = strtok(NULL, sep);
    } 

    free(writeablestring);

    if(found) *found = i;
    return array; 
} 


int main(int argc, char** argv) 
{ 
    char* n_data = "hello 123 ploc"; 

    struct node_t* node = node_create(n_data); 
    if(node)
    {
        printf("node->tuple->n_fields=%d\n", node->tuple->n_fields);

        for(int i = 0; i < node->tuple->n_fields; ++i)
            printf("node->tuple->fields[%d]=%s\n", i, node->tuple->fields[i]);

        node_destroy(node);
    }

    return 0; 
} 

Try something like this instead:

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


struct tuple_t
{ 
    long timestamp; /* instante de criacao do tuplo*/ 
    int n_fields; /* numero de campos deste tuplo */ 
    char** fields; /* array com campos do tuplo */ 
}; 

struct node_t
{ 
    struct tuple_t* tuple; //Entrada na lista 
    struct node_t* next; //o node seguinte da lista 
}; 


char** split_str(const char *, const char *, int *); 
void node_destroy(struct node_t*);

struct node_t* node_create(char* node_data)
{ 
    struct node_t* node = (struct node_t *) malloc(sizeof(struct node_t)); 
    if(!node)
    { 
        printf("Erro ao criar um node!\n"); 
        return NULL; 
    } 

    node->tuple = (struct tuple_t *) malloc(sizeof(struct tuple_t));
    if(!node->tuple)
    {
        printf("Erro ao criar o node->tuple\n");
        node_destroy(node);
        return NULL;
    } 

    node->tuple->timestamp = 0L; 

    node->tuple->fields = split_str(node_data, " ", &(node->tuple->n_fields));
    if(!node->tuple->fields)
    {
        printf("Erro ao criar o node->tuple->node_fields\n");
        node_destroy(node);
        return NULL;
    } 

    node->next = NULL; 

    return node; 
} 

void node_destroy(struct node_t* node)
{
    if(node)
    {
        if(node->tuple)
        {
            if(node->tuple->fields)
            {
                for(int i = 0; i < node->tuple->n_fields; ++i)
                    free(node->tuple->fields[i]);

                free(node->tuple->fields);
            }

            free(node->tuple);
        }

        free(node);
    }
}

char** split_str(const char* str, const char* sep, int* found)
{ 
    if (found) *found = 0;

    int len = strlen(str);

    char** array = (char**) malloc(len * sizeof(char*));
    if(!array)
    {
        printf("Erro ao alocar memoria para o array em split\n");
        return NULL;
    }

    ++len;

    char* writablestring = (char*) malloc(len); 
    if(!array)
    {
        printf("Erro ao alocar memoria para writeablestring em split\n");
        free(array);
        return -1;
    } 

    strncpy(writablestring, str, len);

    char* token = strtok(writablestring, sep); 
    int i = 0;

    while(token)
    { 
        len = strlen(token) + 1;

        array[i] = (char*) malloc(len);
        if(!array[i]) 
        {
            printf("Erro ao alocar memoria para o array item em split\n");

            free(writeablestring);
            for(int j = 0; j < i; ++j)
                free(array[j]);
            free(array);
            return NULL;
        }

        strncpy(array[i], token, len); 
        ++i;

        token = strtok(NULL, sep);
    } 

    free(writeablestring);

    if(found) *found = i;
    return array; 
} 


int main(int argc, char** argv) 
{ 
    char* n_data = "hello 123 ploc"; 

    struct node_t* node = node_create(n_data); 
    if(node)
    {
        printf("node->tuple->n_fields=%d\n", node->tuple->n_fields);

        for(int i = 0; i < node->tuple->n_fields; ++i)
            printf("node->tuple->fields[%d]=%s\n", i, node->tuple->fields[i]);

        node_destroy(node);
    }

    return 0; 
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文