考虑
int main()
{
auto a = new int[0];
delete[] a; // So there's no memory leak
}
Run Code Online (Sandbox Code Playgroud)
在复制初始化和删除之间,您是否允许读取指针a + 1?
此外,该语言是否允许编译器设置a为nullptr?
我正在编写一个C++ 14 JSON库作为练习,并在我的个人项目中使用它.
通过使用callgrind,我发现在字符串压力测试的连续值创建过程std::string中,当前的瓶颈是动态内存分配.确切地说,瓶颈就是要求malloc(...)制造的std::string::reserve.
我已经读过很多现有的JSON库,比如rapidjson使用自定义分配器来避免malloc(...)字符串内存分配期间的调用.
我试图分析rapidjson的源代码,但是大量额外的代码和注释,以及我不确定我正在寻找什么的事实,对我没什么帮助.
std::strings从中获取可用内存?代码说明:
Str是别名std::string.我有一个 C++ 概念来检查对象数组是否可以动态分配:
template< class T, int N >
concept heap_constructible = requires() {
delete[] new T[N];
};
Run Code Online (Sandbox Code Playgroud)
我意外地发现,在零大小数组N=0和不可访问的(例如private:)构造函数的情况下,编译器的评估会出现分歧:
class A {
A();
};
static_assert( !heap_constructible<A, 5> ); // OK everywhere
static_assert( heap_constructible<A, 0> ); // OK in GCC only
Run Code Online (Sandbox Code Playgroud)
只有 GCC 似乎允许零大小分配A-objects。Clang 打印错误:
calling a private constructor of class 'A'
Run Code Online (Sandbox Code Playgroud)
如果概念稍作修改:
template< class T, int N >
concept heap_constructible1 = requires() {
delete[] new T[N]{}; // note additional empty braced list
};
Run Code Online (Sandbox Code Playgroud)
Clang …
我有一个以这种方式描述的类:
class Foo {
int size;
int data[0];
public:
Foo(int _size, int* _data) : size(_size) {
for (int i = 0 ; i < size ; i++) {
data[i] = adapt(_data[i]);
}
}
// Other, uninteresting methods
}
Run Code Online (Sandbox Code Playgroud)
我无法改变那门课程的设计.
如何创建该类的实例?在调用构造函数之前,我必须保留足够的内存来存储其数据,因此它必须在堆上,而不是在堆栈上.我想我想要的东西
Foo* place = static_cast<Foo*>(malloc(sizeof(int) + sizeof(int) * size));
*place = new Foo(size, data); // I mean : "use the memory allocated in place to do your stuff !"
Run Code Online (Sandbox Code Playgroud)
但我找不到办法让它发挥作用.
编辑:正如评论员所注意到的,这不是一个非常好的整体设计(使用非标准技巧data[0]),唉这是一个我不得不使用的库...
该标准在5.3.4/7中说:
当direct-new-declarator中的表达式的值为零时,将调用分配函数以分配不带元素的数组.
......并且,在3.7.3.1/2中:
取消引用作为零大小请求返回的指针的效果是未定义的.
...但是,指针不能是空指针.
由于实际解除引用指针是未定义的行为,是否有任何实现返回指向保护页面的指针?我想这很容易,并且有助于检测错误/提高安全性.
这类似于零大小的数组分配/意味着什么?
我有以下代码
int *p = new int[0];
delete []p;
Run Code Online (Sandbox Code Playgroud)
p获取一个地址并被正确删除.
我的问题是:为什么c ++ Standard首先允许分配零字节?为什么不抛出bad_alloc或一些特殊的异常?
我认为,这只是推迟了灾难性的失败,使程序员的生活变得困难.因为如果要在运行时计算要分配的大小,并且如果程序员正确地假定其分配并尝试向该内存写入内容,则最终会破坏内存!并且崩溃可能发生在代码中的其他位置.
编辑:它在零大小请求时分配了多少内存?
问题:变量n的值是多少,以下代码会导致内存泄漏?
那是代码:
int* Bar(int n)
{
if (n == 1)
throw "exception";
return new int[n];
}
void Foo(int n)
{
int *a = Bar(n);
if (n <= 2)
return;
delete[] a;
}
Run Code Online (Sandbox Code Playgroud)
从5.3.4/7开始
当direct-new-declarator中的表达式的值为零时,将调用分配函数以分配不带元素的数组.
从3.7.3.1/2开始
取消引用作为零大小请求返回的指针的效果是未定义的.
也
即使[new]请求的空间大小为零,请求也会失败.
这意味着你可以做到,但你不能合法地(在所有平台上以明确定义的方式)取消引用你得到的内存 - 你只能将它传递给数组删除 - 你应该删除它.
这是一个有趣的脚注(即不是标准的规范部分,但包含在说明性的傀儡中)附在3.7.3.1/2的句子上
[32.目的是通过调用malloc()或calloc()来实现operator new(),因此规则基本相同.C++与C的不同之处在于要求零请求返回非空指针.
int*a = Bar(1)和Bar(1)抛出异常.它是变量a的构造函数中的异常吗?它会导致内存泄漏吗?
这行代码有什么作用?
new int[];
Run Code Online (Sandbox Code Playgroud)
根据我的编译器的反汇编(VC++ 2012),它的作用如下:
new int[0];
Run Code Online (Sandbox Code Playgroud)
但它是否由C++标准指定?这是法律指令吗?
我有一个Image类,最初我不知道图像的尺寸,所以我只是将data_指针初始化为一个大小为0的数组.后来当我找到图像信息时,我重新初始化data_为一个新的大小.这会在内存中造成任何问题吗?有没有更清洁的方法来做到这一点?
以下是我写的课程:
class Image
{
private:
int numRows_, numCols_;
unsigned char* data_;
public:
Image() : numRows_(0), numCols_(0), data_(new unsigned char[0])
{}
void setData(int r, int c, unsigned char* data)
{
this->numRows_ = r;
this->numCols_ = c;
this->data_ = new unsigned char[r*c];
for (int i = 0; i < r*c; i++)
{
this->data_[i] = data[i];
}
}
int rows();
int cols();
unsigned char* data();
~Image();
};
Run Code Online (Sandbox Code Playgroud)
提前致谢
c++ ×10
new-operator ×4
c++11 ×2
arrays ×1
c ×1
c++14 ×1
constructor ×1
memory-leaks ×1
optimization ×1
sizeof ×1
string ×1