簡體   English   中英

通過 malloc 為 std::string 數組分配 memory 不起作用

[英]Allocating memory thorugh malloc for std::string array not working

我在為字符串數組分配堆上的 memory 時遇到問題。 每次都分配新作品,但 malloc 段錯誤。 我想首先使用 malloc 的原因是我不想不必要地調用構造函數。

這工作正常

std::string* strings = new std::string[6];

這不

std::string* strings = (std::string *)malloc(sizeof(std::string[6]));

我注意到的一件事是,第一個變體(使用新的)分配了 248 個字節的 memory,而第二個只分配了 240 個。無論我收集到的數組的大小如何,這個 8 字節的差異都是恆定的,我找不到差異的來源是什么。

這是段錯誤的整個代碼。

#include <iostream>

void* operator new(size_t size)
{
    std::cout << size << std::endl;
    return malloc(size);
}

void* operator new [](size_t size)
{
    std::cout << size << std::endl;
    return malloc(size);
}

int main() {
    std::string* strings = new std::string[6];
    strings = (std::string *)malloc(sizeof(std::string[6]));

    strings[0] = std::string("test");

    return 0;
}

我注意到的另一件事是,如果我在 malloc 之后使用 memset 將我用 malloc 分配的所有字節設置為 0,則上述代碼似乎有效。為什么這個變體完全有效。 為什么它會因為我將所有字節都設置為 0 而起作用?

malloc()僅分配原始 memory,但它不會在該 memory 內部構造任何對象。

newnew[]都分配 memory 並構造對象。

如果您真的想使用malloc()創建一個 C++ 對象數組(您真的不應該這樣做),那么您將不得不自己使用placement-new調用 object 構造函數,並在 freeingB4 之前調用 object 構造函數,並自己調用 ZA8CFDE6331BD596EBAC96 memory,例如:

std::string* strings = static_cast<std::string*>(
    malloc(sizeof(std::string) * 6)
);

for(int i = 0; i < 6; ++i) {
    new (&strings[i]) std::string;
}

...

for(int i = 0; i < 6; ++i) {
    strings[i].~std::string();
}

free(strings);

在 C++11 和 C++14 中,您應該使用std::aligned_storage來幫助計算數組 memory 的必要大小,例如:

using string_storage = std::aligned_storage<sizeof(std::string), alignof(std::string)>::type;

void *buffer = malloc(sizeof(string_storage) * 6);

std::string* strings = reinterpret_cast<std::string*>(buffer);

for(int i = 0; i < 6; ++i) {
    new (&strings[i]) std::string;
}

...

for(int i = 0; i < 6; ++i) {
    strings[i].~std::string();
}

free(buffer);

在 C++17 及更高版本中,您應該直接使用std::aligned_alloc()而不是malloc() ,例如:

std::string* strings = static_cast<std::string*>(
    std::aligned_alloc(alignof(std::string), sizeof(std::string) * 6)
);

for(int i = 0; i < 6; ++i) {
    new (&strings[i]) std::string;
}

...

for(int i = 0; i < 6; ++i) {
    strings[i].~std::string();
}

std::free(strings);

通過new分配意味着構造函數運行。 請始終將newdelete與 C++ 類(並且std::string是 C++ 類)一起使用,只要可以。

當您執行malloc() / free()時,僅 memory 分配完成,構造函數(析構函數)不運行。 這意味着,object 未初始化。 從技術上講,您可能仍然可以使用placement new (即new(pointer) Type )來初始化它,但是使用經典new會更好,更符合要求。

如果你想分配多個對象,這就是容器的用途。 請使用它們。 多名頂級工程師致力於std::vector<>std::array<>std::set<>std::map<>工作並達到最佳狀態 - 在性能、穩定性方面很難擊敗他們或其他指標,即使您這樣做,同一家公司的下一位編碼員也需要學習您的特定數據結構。 因此,建議不要在可以使用容器的地方使用自定義和本地實現的分配,除非出於非常強烈的原因(或者,當然,出於教學目的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM