2016-12-01 51 views
4

我很想知道如果在字符串周圍保留一個元數據的頭部會是安全的,而不是實現相關的?在malloc'd字符串之前保存元數據是否安全?

我不知道,如果下面將跨平臺工作或有東西,可能會導致讀取錯誤sizetotal字段或是否會有這樣做對緩衝區realloc有問題嗎?

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

typedef struct{ 
    int size; 
    int total; 
    char buf[]; 
} String; 

int get_str_size(char *str){ 
    String *pointer = (void*)(str-sizeof (String)); 
    return pointer->size; 
} 

int get_str_total(char *str){ 
    String *pointer = (void*)(str-sizeof (String)); 
    return pointer->total; 
} 

char *init_string(int sz){ 
    size_t header_size = 1 + sz + sizeof(String); 
    String *pointer = calloc(header_size, 1); 

    pointer->total = 0; 
    pointer->size = sz; 

    return pointer->buf; 
} 

char *realloc_string(char *str, int sz){ 
    int old = get_str_size(str); 
    int new = old + sz; 

    String *pointer1 = (void*)(str-sizeof (String)); 
    size_t header_size = 1 + new + sizeof(String); 
    String *pointer2 = realloc(pointer1, header_size); 

    return pointer2->buf; 
} 

int main(void){ 
    char *str = NULL; 
    str = init_string(10); 

    printf("Length of str:%d\n", get_str_size(str)); 
    printf("Total malloc'd:%d\n", get_str_total(str)); 
    free(str - sizeof (String)); 

    return 0; 
} 
+1

我看不到任何問題。但是我會添加'free_string'函數。 – freestyle

+1

我認爲除了缺少錯誤檢查之外,它是相當安全的。我想如果分配失敗,我會讓'init_string'和'realloc_string'返回'NULL'。其他我要做的事情包括將'init_string'重命名爲'alloc_string',當'str'爲'NULL'時使'realloc_string'與'init_string'相同,並添加'free_string'函數接受一個有效的字符串或NULL指針。 –

+0

請注意,MS Windows中的'BSTR'字符串做了類似的事情;它們在返回的指針前有一個32位長的前綴。 –

回答

1

這是不安全的。

它沒有未定義的行爲(UB)也沒有實現定義的行爲,因爲合法的,除了小的int/size_t問題。

不幸的是代碼隱藏太多。 @Jonathan Leffler。考慮下面編譯的代碼,然後調用UB。

printf("%d\n", get_str_size("Hello Word")); 

組函數將使用類型String作爲參數,而不是char *更好。這就是類型檢查的目的。


小問題。

C 字符串是數組。數組索引最好使用size_t類型。 int可能太窄。

String *String_copy(const char *src) { 
    size_t len = strlen(src); 
    //       v-v Overflow potential 
    String *dest = init_string(len); 
    ... 
    return dest; 
} 

可能int溢出。重新預防。

//      v----v int math 
// size_t header_size = 1 + sz + sizeof(String); 
size_t header_size = sz + sizeof(String) + 1; 
// or 
size_t header_size = sizeof(String) + sz + 1; 

代碼缺乏其他功能,應補充集。 @Ian

缺少錯誤檢查,但假設這是爲了簡化代碼表示。

相關問題