首页 > 解决方案 > PPP Stroustrup 练习 - 将 C 风格的字符串复制到它在自由存储上分配的内存中

问题描述

我正在解决 Stroustrup 的 PPP 书中的以下练习(17.4):

编写一个函数char* strdup(const char* ),将 C 风格的字符串复制到它在空闲存储上分配的内存中。不要使用任何标准库函数。

这是我的实现,编译得很好。我对运行该函数时发现的错误消息有疑问。

#include <iostream>
#include <string>
char* strdup(const char* s) {
    if (s==0) return 0;

    // get number of char in s
    int n = 0;
    while (s[n] != 0)
        ++n;

    // allocate memory with room for terminating 0
    char* pc = new char[n+1];

    // copy string
    for (int i = 0; s[i]; ++i)
        pc[i] = s[i];
    pc[n] = 0;  // zero at the end: it's a C-style string

    delete[] s;
    return pc;
}

int main()
try {
    std::string str;
    char* cstr;
    while (std::cin>>str && str!="quit") {
        cstr = strdup(&str[0]);
        std::cout << cstr << "\n";
        delete[] cstr;
    }
}
catch (std::exception& e) {
    std::cerr << "exception: " << e.what() << std::endl;
}
catch (...) {
    std::cerr << "exception\n";
}

它可以编译,但是当我运行它并写入第一个字符时,出现pointer being freed was not allocated错误。如果我删除delete[] s,那么我没有内存泄漏,它运行得很好。但是为什么(显然)不这样做是正确delete[]s?是不是因为没有被分配new

标签: c++arraysstringpointersdelete-operator

解决方案


Astd::string确实管理它用于存储字符串的内存。在main你做

 std::string str;

cstr = strdup(&str[0]);

但是您对参数的strdup调用。delete[] s;

这是你已经知道的。现在考虑析构函数std::string在超出范围时确实已经清理了内存。使用的缓冲区std::string不能被删除两次。你不许叫delete&str[0]您只需要delete通过创建的对象new

还有小字符串优化。在这种情况下&str[0],不指向您可以删除的堆分配缓冲区。


PS:0当您应该使用nullptr指针和'\0'空终止符时,您正在使用。


推荐阅读