首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在另一个函数中使用asprintf为字符串分配内存

在另一个函数中使用asprintf为字符串分配内存
EN

Stack Overflow用户
提问于 2015-11-19 19:16:27
回答 2查看 160关注 0票数 1

我想知道这是否是个好做法:

  • 从函数内的数据库中获取字符串
  • 使用asprintf为要存储在传递给函数的结构中的字符串分配内存

我已经读过几篇关于内存管理和内存泄漏的帖子和文章。除此之外,我还读到,在函数中分配内存被认为是不好的,但是如果我在函数中只知道如何分配内存,那么我应该如何分配内存,因为要分配的内存大小取决于数据库中字符串的长度?

代码语言:javascript
复制
typedef struct{
    int age;
    char * name;
}my_struct;

bool get_data(my_struct * p){
    bool succes=false;

    if(mysql_real_connect(my, "localhost", SQL_USER, SQL_PASS, SQL_BASE, 0, NULL, 0) == NULL){
        fprintf(stderr,"MYSQL-connection error!");
        success=false;
    }

    if(mysql_query(my, "SELECT * FROM Persons WHERE id=1")){ // Assume this would be where the real data came from
        fprintf(stderr, "sql_query: %s\nfailed\n", query);
        success=false;
    }else{
        MYSQL_RES * result=NULL;
        result = mysql_store_result(my);

        if(mysql_num_rows(result) == 1){
            MYSQL_ROW row=NULL;
            row=mysql_fetch_row(result);
            p->age=atoi(row[1]);
            if(asprintf(&p->name, "%s", row[2])==-1){
                success=false;
                p->name=NULL;
            }else{
                success=true;
            }
        }else{
            success=false;
        }
        mysql_free_result(result);
    }

    mysql_close(my);
    return(success);
}

void init_my_struct(my_struct * s){
    s->age=0;
    s->name=""; // This should be: s->name=NULL;
}

void reset_my_struct(my_struct * s){
    if(s->name)free(s->name);
    init_my_struct(s);
}

int main(int argc, char **argv){
    my_struct person;
    init_my_struct(&person);
    if(get_data(&person)){
        puts("OK");
    }else{
        puts("Not OK");
    }
    reset_my_struct(&person); // Frees memory if it was allocated
}

另外:我使用自己编写的函数来初始化和重置/取消结构my_struct,这是否是安全的?或者它是一个定时炸弹的记忆破坏?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-19 19:40:04

在一个函数中分配内存是可以的。您所读到的文章可能意味着,最好先分配内存,然后在相同的函数中释放它。但是,正如您所发现的,这只有在调用方(在您的情况下是main)知道要分配多少内存时才有可能。在这种情况下,我建议您在get_data函数的文档中添加一个注释,说明它在p中分配内存,这应该是freed。

拥有独立的函数来初始化和销毁struct也是非常好的。但是,init_my_struct函数在reset_my_struct中会导致未定义的行为,因为它将(n个空的)字符串常量""分配给name成员。如果reset_my_struct试图对此字符串进行free,则会导致未定义的行为,因为即使是空字符串也不是NULL/0/false。你应该把它改为:

代码语言:javascript
复制
s->name = NULL;

最后,您可以使用asprintf,但是如果您只想复制字符串而不添加任何其他内容,那么strdup可能更适合。例如:

代码语言:javascript
复制
p->name = strdup(row[2]);
if(p->name == NULL){
    success=false;
}else{
票数 2
EN

Stack Overflow用户

发布于 2015-11-19 19:35:38

这看起来不错,除了一件事:

代码语言:javascript
复制
void init_my_struct(my_struct * s){
    s->age=0;
    s->name="";     // assigns a const char * to s->name
}

在这里,您将s->name设置为非空值。空字符串与空字符串不一样。它是一个包含值0的单个字符数组,即在空终止符之前为空结束的字符串。

如果在向其分配任何内容之前尝试使用free(s->name),则可能会出现核心转储,因为malloc没有返回常量字符串""

在函数中分配内存是很好的,特别是当计算出需要多少内存是留给函数的任务时。但是,您必须确保在函数调用之后的某个时候对其进行free

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33812522

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档