I am currently trying to read a BMP file and write it back out, and when I try and read the headers, it always ends up giving me a segfault. I have tried multiple different solutions from stack as well as other places and now am completely stuck.
Here's the BMPImage.h file:
#pragma once
#include <vector>
#include <cstdint>
#include <string>
#include "../fileHeaders/BMPHeaders.hpp"
#ifndef BMPIMAGE_H
#define BMPIMAGE_H
namespace mediaObjs {
class BMPIMAGE {
public:
//Constructors
BMPIMAGE(std::string filename);
BMPIMAGE(std::string filename, BMPFILEHEADER fileHeader,
BMPINFOHEADER infoHeader, RGBQUAD colourTable, std::vector<uint8_t> pixel_data);
//IO methods
void loadFile();
void writeFile();
//Getters
std::string getFilename();
BMPFILEHEADER getFileHeader();
BMPINFOHEADER getInfoHeader();
RGBQUAD getColourTable();
std::vector<uint8_t> getPixelData();
//Setters/Modifiers
std::vector<uint8_t>* modifyPixelData();
private:
std::string m_filename;
BMPFILEHEADER m_fileHeader;
BMPINFOHEADER m_infoHeader;
RGBQUAD m_colourTable;
std::vector<uint8_t> m_pixel_data;
};
}
#endif
Here's the BMPImage.cpp file:
#include "./BMPImage.h"
#include <fstream>
#include <algorithm>
using namespace mediaObjs;
BMPIMAGE::BMPIMAGE(std::string filename)
: m_filename {filename}
{}
BMPIMAGE::BMPIMAGE(std::string filename, BMPFILEHEADER fileHeader,
BMPINFOHEADER infoHeader, RGBQUAD colourTable,
std::vector<uint8_t> pixel_data)
: m_filename {filename}, m_fileHeader {fileHeader},
m_infoHeader {infoHeader}, m_colourTable {colourTable},
m_pixel_data {pixel_data}
{}
void BMPIMAGE::loadFile()
{
std::ifstream file(this->m_filename, std::ios::in | std::ios::binary);
//Read the file headers.
BMPFILEHEADER fileHeader __attribute__((unused));
file.read(reinterpret_cast<char*> (fileHeader.bfType), sizeof(uint16_t));
file.read(reinterpret_cast<char*> (fileHeader.bfSize), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (fileHeader.bfReserved1), sizeof(uint16_t));
file.read(reinterpret_cast<char*> (fileHeader.bfReserved2), sizeof(uint16_t));
file.read(reinterpret_cast<char*> (fileHeader.bfOffBits), sizeof(uint32_t));
this->m_fileHeader = fileHeader;
//Read the info headers.
BMPINFOHEADER infoHeader __attribute__((unused));
file.read(reinterpret_cast<char*> (infoHeader.biSize), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biWidth), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biHeight), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biPlanes), sizeof(uint16_t));
file.read(reinterpret_cast<char*> (infoHeader.biBitCount), sizeof(uint16_t));
file.read(reinterpret_cast<char*> (infoHeader.biCompression), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biSizeImage), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biXPelsPerMetre), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biYPelsPerMetre), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biClrUsed), sizeof(uint32_t));
file.read(reinterpret_cast<char*> (infoHeader.biClrImportant), sizeof(uint32_t));
this->m_infoHeader = infoHeader;
//Read the colour table.
RGBQUAD colourTable __attribute__((unused));
file.read(reinterpret_cast<char*> (colourTable.red), sizeof(uint8_t));
file.read(reinterpret_cast<char*> (colourTable.green), sizeof(uint8_t));
file.read(reinterpret_cast<char*> (colourTable.blue), sizeof(uint8_t));
file.read(reinterpret_cast<char*> (colourTable.reserved), sizeof(uint8_t));
this->m_colourTable = colourTable;
//Read the pixel data.
std::vector<char> buffer(m_infoHeader.biSizeImage);
file.read(buffer.data(), m_infoHeader.biSizeImage);
std::copy(std::begin(buffer), std::end(buffer), std::back_inserter(m_pixel_data));
file.close();
}
void BMPIMAGE::writeFile()
{
std::ofstream file(this->m_filename, std::ios::out | std::ios::binary);
//Write the file headers.
file.write(reinterpret_cast<char*> (this->m_fileHeader.bfType), sizeof(uint16_t));
file.write(reinterpret_cast<char*> (this->m_fileHeader.bfSize), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_fileHeader.bfReserved1), sizeof(uint16_t));
file.write(reinterpret_cast<char*> (this->m_fileHeader.bfReserved2), sizeof(uint16_t));
file.write(reinterpret_cast<char*> (this->m_fileHeader.bfOffBits), sizeof(uint32_t));
//Write the info headers.
file.write(reinterpret_cast<char*> (this->m_infoHeader.biSize), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biWidth), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biHeight), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biPlanes), sizeof(uint16_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biBitCount), sizeof(uint16_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biCompression), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biSizeImage), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biXPelsPerMetre), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biYPelsPerMetre), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biClrUsed), sizeof(uint32_t));
file.write(reinterpret_cast<char*> (this->m_infoHeader.biClrImportant), sizeof(uint32_t));
//Write the colour table.
file.write(reinterpret_cast<char*> (this->m_colourTable.red), sizeof(uint8_t));
file.write(reinterpret_cast<char*> (this->m_colourTable.green), sizeof(uint8_t));
file.write(reinterpret_cast<char*> (this->m_colourTable.blue), sizeof(uint8_t));
file.write(reinterpret_cast<char*> (this->m_colourTable.reserved), sizeof(uint8_t));
//Write the pixel data.
uint8_t* pixel_data = &(this->m_pixel_data[0]);
file.write(reinterpret_cast<char*> (pixel_data), this->m_pixel_data.size());
file.close();
}
std::string BMPIMAGE::getFilename()
{
return this->m_filename;
}
BMPFILEHEADER BMPIMAGE::getFileHeader()
{
return this->m_fileHeader;
}
BMPINFOHEADER BMPIMAGE::getInfoHeader()
{
return this->m_infoHeader;
}
RGBQUAD BMPIMAGE::getColourTable()
{
return this->m_colourTable;
}
std::vector<uint8_t> BMPIMAGE::getPixelData()
{
return this->m_pixel_data;
}
std::vector<uint8_t>* BMPIMAGE::modifyPixelData()
{
return &(this->m_pixel_data);
}
And this is the BMPHeaders.h file:
#pragma once
#include <cstdint>
#include <fstream>
#ifndef BMPHEADERS_H
#define BMPHEADERS_H
//Defines the BitMap File Header structure. Contains the information about the BitMap file.
struct __attribute__((__packed__)) BMPFILEHEADER
{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
//Defines the BitMap Info Header structure. Contains the metadata about the actual BitMap image.
struct __attribute__((__packed__)) BMPINFOHEADER
{
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMetre;
uint32_t biYPelsPerMetre;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
//Defines the RGB structure for the BitMap file.
struct __attribute__((__packed__)) RGBQUAD
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t reserved;
};
#endif
And the valgrind output dump:
==1488== Memcheck, a memory error detector
==1488== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1488== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==1488== Command: ./image-resizer
==1488==
==1488== error calling PR_SET_PTRACER, vgdb might block
Starting the deserialisation process.
Found the image file.
==1488== Use of uninitialised value of size 8
==1488== at 0x4994D8E: std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x495DC84: std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x496BA81: std::istream::read(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x10AD01: mediaObjs::BMPIMAGE::loadFile() (BMPImage.cpp:26)
==1488== by 0x10A5E6: main (main.cpp:23)
==1488==
==1488== Invalid write of size 1
==1488== at 0x4994D8E: std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x495DC84: std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x496BA81: std::istream::read(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x10AD01: mediaObjs::BMPIMAGE::loadFile() (BMPImage.cpp:26)
==1488== by 0x10A5E6: main (main.cpp:23)
==1488== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1488==
==1488==
==1488== Process terminating with default action of signal 11 (SIGSEGV)
==1488== Access not within mapped region at address 0x0
==1488== at 0x4994D8E: std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x495DC84: std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x496BA81: std::istream::read(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1488== by 0x10AD01: mediaObjs::BMPIMAGE::loadFile() (BMPImage.cpp:26)
==1488== by 0x10A5E6: main (main.cpp:23)
==1488== If you believe this happened as a result of a stack
==1488== overflow in your program's main thread (unlikely but
==1488== possible), you can try to increase the size of the
==1488== main thread stack using the --main-stacksize= flag.
==1488== The main thread stack size used in this run was 8388608.
==1488==
==1488== HEAP SUMMARY:
==1488== in use at exit: 8,705 bytes in 3 blocks
==1488== total heap usage: 6 allocs, 3 frees, 85,546 bytes allocated
==1488==
==1488== LEAK SUMMARY:
==1488== definitely lost: 0 bytes in 0 blocks
==1488== indirectly lost: 0 bytes in 0 blocks
==1488== possibly lost: 0 bytes in 0 blocks
==1488== still reachable: 8,705 bytes in 3 blocks
==1488== suppressed: 0 bytes in 0 blocks
==1488== Reachable blocks (those to which a pointer was found) are not shown.
==1488== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1488==
==1488== Use --track-origins=yes to see where uninitialised values come from
==1488== For lists of detected and suppressed errors, rerun with: -s
==1488== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
[1] 1488 segmentation fault (core dumped) valgrind --leak-check=full ./image-resizer
Some help, or even a pointer in the right direction would really be appreciated.
EDIT: I have updated the code in accordance with #PaulMckenzie 's answer.
reinterpret_cast<char*> (colourTable.red)
cast a value to a target pointer for read or write, this is nonsense,
you should read or write to the address of value,
try :
reinterpret_cast<char*> (&colourTable.red)
and apply to all others similar value-to-pointer casts...
The obvious errors are the following:
//Read the pixel data.
unsigned char* buffer = new unsigned char[this->m_infoHeader.biSizeImage];
//...
for(int i = 0; i <= sizeof(buffer); ++i)
The first issue is that sizeof(buffer) does not give you the number of bytes allocated. It will return the sizeof(unsigned char*), which is more than likely 4 or 8.
The second issue is the usage of <= in the for loop. Even if you specified the correct number of bytes to process, there will be a memory overwrite on the last iteration of the for loop.
The quick fixes would be:
//Read the pixel data.
unsigned char* buffer = new unsigned char[this->m_infoHeader.biSizeImage];
file.read(reinterpret_cast<char*>(buffer), m_infoHeader.biSizeImage);
for(int i = 0; i < m_infoHeader.biSizeImage; ++i){
this->m_pixel_data.push_back(buffer[i]);
}
But a better (and safer) alternative would be:
//Read the pixel data.
#include <vector>
#include <iterator>
#include <algorithm>
//...
std::vector<char> buffer(m_infoHeader.biSizeImage);
file.read(buffer.data(), m_infoHeader.biSizeImage);
std::copy(std::begin(buffer), std::end(buffer), std::back_inserter(m_pixel_data));
Using std::vector, there is no need to issue a delete [] buffer; at the end of this processing. In addition, the std::copy replaces the hard-coded for loop that is issuing the push_back calls on the m_pixel_data vector.
Hello !
I have a question about memory with jsoncpp. I have to load large JSon file (55 MB) in c++ with jsoncpp. I noticed my program use lot of RAM. I tried something, just open, parse and close the JSON file. After the closing of file the memory usage did'nt decrese at all.
I also tried with RapidJson and after returning a lot of memory is freed.
I'm using Linux
I tried this code, which prints statm file in /proc/PID/statm before and after Jsoncpp parse.
It prints the memory before, during and after the parse function.
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/document.h>
void printmem()
{
char tmp[128];
std::string t;
sprintf(tmp, "/proc/%d/statm", getpid());
std::ifstream ifs(tmp);
std::getline(ifs, t);
std::cout << t <<"\n";
ifs.close();
}
void jsoncpp()
{
std::ifstream ifs("../../../AlloDB/db.json");
Json::CharReaderBuilder builder;
Json::Value value;
JSONCPP_STRING errs;
Json::parseFromStream(builder, ifs, &value, NULL);
ifs.close();
printmem();
}
void rapid_json()
{
using namespace rapidjson;
std::ifstream ifs("../../../AlloDB/db.json");
std::string t;
IStreamWrapper isw(ifs);
Document d;
d.ParseStream(isw);
printmem();
}
int main(int argc, char** argv)
{
printmem();
//jsoncpp();
rapid_json();
printmem();
}
The result is:
For jsoncpp
2552 629 516 51 0 188 0
107744 106364 1052 51 0 105380 0
107744 106364 1052 51 0 105380 0
So before the parse, the total memoy used is 2552*4096 +/-= 10 MiB. During and after the function memory usage is strictly the same 107744*4096 +/-= 420 MiB.
For RapidJson:
2552 642 530 51 0 188 0
24275 22871 1056 51 0 21911 0
4140 2780 1056 51 0 1776 0
RapidJson free a lot of memory but not etire.
Jsoncpp should free his memory after returning jsoncpp(), isnt it ? I tried Valgrind with this program (with jsoncpp), and there is no memory leak.
==133628== Memcheck, a memory error detector
==133628== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==133628== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==133628== Command: bin/Debug/db
==133628==
50448 39807 1539 498 0 47403 0
649572 639457 1671 498 0 646527 0
440676 431819 1671 498 0 437631 0
==133628==
==133628== HEAP SUMMARY:
==133628== in use at exit: 0 bytes in 0 blocks
==133628== total heap usage: 5,917,609 allocs, 5,917,609 frees, 601,544,185 bytes allocated
==133628==
==133628== All heap blocks were freed -- no leaks are possible
==133628==
==133628== For lists of detected and suppressed errors, rerun with: -s
==133628== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Why jsoncpp does not free memory in returning the jsoncpp() function ?
After parsing i dont need to acces the data, hot to clean it ?
Thanks
The following code, when built on ubuntu creates an executable.
#include <stdio.h>
void otherfunc(FILE* fout){
fclose(fout);//Line 4
fout = fopen("test.txt", "w");//Delete contents and create a new file//Line 5
setbuf(fout, 0);//Line 6
}
int main() {
FILE *fout = fopen("test.txt", "r");//Line 10
if (fout) {
//file exists and can be opened
fclose(fout);//Line 13
fout = fopen("test.txt", "a");//Line 14
setbuf(fout, 0);
}
else {
//file doesn't exists or cannot be opened
fout = fopen("test.txt", "a");//Line 19
}
otherfunc(fout);//Line 22
fclose(fout);//Line 24
return 0;
}
When run through valgrind, valgrind gives the following warnings:
==13569== Invalid read of size 4
==13569== at 0x4EA7264: fclose##GLIBC_2.2.5 (iofclose.c:53)
==13569== by 0x400673: main (newmain.cpp:24)
==13569== Address 0x52042b0 is 0 bytes inside a block of size 552 free'd
==13569== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13569== by 0x4EA7362: fclose##GLIBC_2.2.5 (iofclose.c:84)
==13569== by 0x4005CD: otherfunc(_IO_FILE*) (newmain.cpp:4)
==13569== by 0x400667: main (newmain.cpp:22)
==13569== Block was alloc'd at
==13569== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13569== by 0x4EA7CDC: __fopen_internal (iofopen.c:69)
==13569== by 0x400657: main (newmain.cpp:19)
Essentially, it is complaining that the fclose(fout); on Line 24 is closing an already freed memory that was freed on line 4 fclose(fout); within otherfunc(). But the Line 24's fclose(fout); is meant to close the fopen() performed on Line 5.
At any point in time in the code, whenever a fclose() is called, there is always exactly one open fopen(). Why is this then an invalid read as reported by valgrind?
otherfunc takes a file pointer by value. So the value you've assigned at line 5 is lost after returning from otherfunc and when it returns into main the value of fout there remains unchanged. It contains a dangling file pointer value that you've closed at line 4. Therefore a call to close on line 24 will receive an invalid pointer.
I am using libcurl in my C++ program to get data from a link. The program is getting result but whenever I do valgrind I see a huge memory leak.
This is my code:
#include <string>
#include <iostream>
#include <curl/curl.h>
#include <map>
using namespace std;
int main(){
string url_;
string paramname_;
string paramvalue_;
cout << "Enter domain name(without parameters): ";
cin >> url_;
cout << "Enter parameter name: ";
cin >> paramname_;
cout << "Enter parameter value: ";
cin >> paramvalue_;
CURL* c;
curl_global_init(CURL_GLOBAL_DEFAULT);
c = curl_easy_init();
string finalurl_ = url_ + "?" + paramname_ + "=" + paramvalue_;
cout << finalurl_ << endl;
curl_easy_setopt(c, CURLOPT_URL, finalurl_.c_str());
cout << curl_easy_perform(c);
curl_easy_cleanup(c);
curl_global_cleanup();
//free(c);
return 0;
}
This is what I get while running valgrind:
==2379== LEAK SUMMARY:
==2379== definitely lost: 7,648 bytes in 116 blocks
==2379== indirectly lost: 1,240 bytes in 27 blocks
==2379== possibly lost: 2,152 bytes in 51 blocks
==2379== still reachable: 103,874 bytes in 192 blocks
==2379== suppressed: 612,674 bytes in 228 blocks
==2379==
==2379== For counts of detected and suppressed errors, rerun with: -v
==2379== ERROR SUMMARY: 130 errors from 130 contexts (suppressed: 19 from 15)
[1] 2379 segmentation fault valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
One of the definitely lost places while running valgrind is:
==2379== 224 (64 direct, 160 indirect) bytes in 1 blocks are definitely lost in loss record 341 of 381
==2379== at 0x10009C232: calloc (vg_replace_malloc.c:714)
==2379== by 0x100E54BA0: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E54C4D: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E54C4D: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E5A72D: getClass_impl(char const*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E5AAF2: object_setClass (in /usr/lib/libobjc.A.dylib)
==2379== by 0x10067B8BD: __CFInitialize (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==2379== by 0x10001D846: ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==2379== by 0x10001DC12: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==2379== by 0x1000194A9: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==2379== by 0x100019440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==2379== by 0x100019440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
I am compiling the program using g++:
g++ -std=c++11 -g -o test -lcurl test.cpp
I am looking for ways to free up the memory. Any help would be appreciated.
During development of proprietary app. I have noticed memory leak, related to std::string in a MS Visual C++ 2013, Update 4.
Take a look at the following (basic) code prototype which causes memory leak:
static std::string MemoryLeakTest()
{
static size_t const test_size = 2002;
std::unique_ptr<char[]> result1(new char[test_size]);
std::string result2(result1.get(), test_size);
return result2;
}
calling it by:
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
Am I doing something wrong, or is it a memory leak in a Visual C++ STL?
P.S. this is DebugView output showing mem leak detected by VLD:
[11140] WARNING: Visual Leak Detector detected memory leaks!
[11140] ---------- Block 3 at 0x00A95620: 2002 bytes ----------
[11140] Leak Hash: 0x1DA884B6, Count: 1, Total 2002 bytes
[11140] Call Stack (TID 9568):
[11140] 0x0FF5C260 (File and line number not available): MSVCR120D.dll!operator new
[11140] f:\dd\vctools\crt\crtw32\stdcpp\newaop.cpp (6): TestCpp.exe!operator new[] + 0x9 bytes
[11140] c:\work\testcpp\testcpp.cpp (307): TestCpp.exe!MemoryLeakTest + 0xA bytes
[11140] c:\work\testcpp\testcpp.cpp (401): TestCpp.exe!wmain + 0x9 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (623): TestCpp.exe!__tmainCRTStartup + 0x19 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): TestCpp.exe!wmainCRTStartup
[11140] 0x75557C04 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0x24 bytes
[11140] 0x77C4B54F (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x8F bytes
[11140] 0x77C4B51A (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
[11140] Data:
Tried your code with Deleaker and it couldn't find any leak.
Then tried this code:
while (true)
{
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
}
Task Manager shows that memory usage remains the same: no leaks.
I think this is a bug in VLD, you can find that std::unique_ptr really frees the memory, just step into during debugging, look:
~unique_ptr() _NOEXCEPT
{ // destroy the object
_Delete();
}
Go further:
void _Delete()
{ // delete the pointer
if (this->_Myptr != pointer())
this->get_deleter()(this->_Myptr);
}
};
Go further:
void operator()(_Ty *_Ptr) const _NOEXCEPT
{ // delete a pointer
static_assert(0 < sizeof (_Ty),
"can't delete an incomplete type");
delete[] _Ptr;
}
};
Aha, delete[] is called!
The call
std::unique_ptr<char[]> result1(new char[test_size]);
is correct. The tricky part is NOT to write std::unique_ptr<char>, which also compiles and can cause a memory leak (unique_ptr calls delete to release resource. When initialized with new[], we need to instruct unique_ptr to call the correct delete[]).
The std::string constructor call is also OK and it's very unlikely there's a memory leak. The std::string can be initialized from a C-style pointer in the same way.
I don't see any memory leak in your code snippet. How do you know it's a memory leak?