如何对动态分配的数据进行const限定?

时间:2018-07-25 07:53:39

标签: c pointers memory-management const qualifiers

根据this answer,不应删除常量,因为常量可能不会首先分配。但是,在某些情况下,我想保护动态分配的数据。例如,在管理用户会话时,我想确保像当前用户名这样的数据不会被其他功能意外覆盖,但是在从中解析会话数据时确实会分配这些数据。请求。

这是一个代码示例,可以帮助您更好地理解。但是请记住,事情已经大大简化了。

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


const char *request = "www.example.com/index?first-name=SOME&last-name=DUDE";

char *get_username_from_request(const char *req) {
    char *first_name = strstr(req, "first-name") + strlen("first-name") + 1;
    char *last_name = strstr(req, "last-name") + strlen("last-name") + 1;

    char *username = malloc(10);
    memcpy(username, first_name, 4);
    username[4] = ' ';
    memcpy(username + 5, last_name, 4);

    /* The returned string is "SOME DUDE" */
    return username;
}

int main(void) {
    char *username = get_username_from_request(request);
    printf("Welcome, %s.\n", username);
    free(username);
    return 0;
}

我真的想改用const char *username = get_username_from_request(request);,但是当我进行此更改时,Clang会发出警告:

/Applications/CLion.app/Contents/bin/cmake/bin/cmake --build /Users/nalzok/CLionProjects/zero/cmake-build-debug --target zero -- -j 2
Scanning dependencies of target zero
[ 50%] Building C object CMakeFiles/zero.dir/main.c.o
/Users/nalzok/CLionProjects/zero/main.c:24:10: warning: passing 'const char *' to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
    free(username);
         ^~~~~~~~
/usr/include/stdlib.h:151:18: note: passing argument to parameter here
void     free(void *);
                    ^
1 warning generated.
[100%] Linking C executable zero
[100%] Built target zero

任何想法都值得赞赏。

†​​:好,believe it or not,我正在用C编写Web应用程序。

1 个答案:

答案 0 :(得分:2)

首先,您必须了解,没有任何事情可以阻止编译后的代码覆盖任何数据,无论是否声明为constconst的正确性仍然可以帮助您发现代码中的逻辑错误,所以这是一个好主意。

对于您的具体问题,我建议在此处隐藏一些类似OOP的信息。您可以例如为用户会话建模:

session.h

#ifndef SESSION_H
#define SESSION_H

typedef struct Session Session;

Session *Session_create(void);
int Session_setUsername(Session *self, const char *username);
const char *Session_Username(const Session *self);
void Session_destroy(Session *self);

#endif

session.c

#include <stdlib.h>
#include <string.h>
#include "session.h"

struct Session
{
    char *username;
};

Session *Session_create(void)
{
    Session *self = calloc(1, sizeof *self);
    return self;
}

int Session_setUsername(Session *self, const char *username)
{
    free(self->username);
    self->username = malloc(strlen(username) + 1);
    if (!self->username) return -1;
    strcpy(self->username, username);
    return 0;
}

const char *Session_Username(const Session *self)
{
    return self->username;
}

void Session_destroy(Session *self)
{
    if (!self) return;
    free(self->username);
    free(self);
}

现在,如果您的代码中有const Session *,您将无法操作任何会话数据。您只能获得指向您的用户名的const指针。