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.
Related
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
Dynamic c-string 'textString' causes Segmentation fault 11 when used by a class member function to be displayed.
#include "Text.h"
#include <iostream>
#include <cstring>
using namespace std;
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength];
strcpy(textString, textArray);
cout << textString << endl;
}
Text::~Text()
{
delete[] textString;
}
void Text::displayText() const
{
cout << textString << endl;
}
My provided driver:
#include <iostream>
#include "Text.h"
using namespace std;
int main()
{
Text *myString1;
char tvshow[1000];
cout << "\n\nWhat is the most recent TV show you watched?\n";
cin.getline(tvshow, 1000);
myString1 = new Text(tvshow);
cout << "\n\nTV SHOW:\t";
myString1->displayText();
cout << "\t# CHARACTERS:\t" << myString1->getLength() << endl;
return 0;
}
In the Constructor for the Text class, the line cout << textString << endl; works as intended. However, when the main function calls myString1->displayText();, bash ends the program with Segmentation fault: 11.
Any help would be greatly appreciated. Thank you.
Additionaly to what Algirdas says, your other problem is, that you actually don't assign the class member textString (assuming you have one), but shadow it in your constructor.
Change your constructor to something like this:
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
textString = new char[textLength + 1];
strcpy(textString, textArray);
cout << textString << endl;
}
Note the missing char * in front of textString.
How did I spot this?
As with any other segfault, you should learn how to debug. Your best tools are gdb and valgrind. Running this with valgrind gives me:
$ echo franz | valgrind ./a.out
==6222== Memcheck, a memory error detector
==6222== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6222== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6222== Command: ./a.out
==6222==
What is the most recent TV show you watched?
franz
TV SHOW: ==6222== Invalid read of size 1
==6222== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222== by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222== by 0x108E70: main (a.cpp:51)
==6222== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6222==
==6222==
==6222== Process terminating with default action of signal 11 (SIGSEGV)
==6222== Access not within mapped region at address 0x0
==6222== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222== by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222== by 0x108E70: main (a.cpp:51)
==6222== If you believe this happened as a result of a stack
==6222== overflow in your program's main thread (unlikely but
==6222== possible), you can try to increase the size of the
==6222== main thread stack using the --main-stacksize= flag.
==6222== The main thread stack size used in this run was 8388608.
==6222==
==6222== HEAP SUMMARY:
==6222== in use at exit: 14 bytes in 2 blocks
==6222== total heap usage: 5 allocs, 3 frees, 77,838 bytes allocated
==6222==
==6222== LEAK SUMMARY:
==6222== definitely lost: 6 bytes in 1 blocks
==6222== indirectly lost: 0 bytes in 0 blocks
==6222== possibly lost: 0 bytes in 0 blocks
==6222== still reachable: 8 bytes in 1 blocks
==6222== suppressed: 0 bytes in 0 blocks
==6222== Rerun with --leak-check=full to see details of leaked memory
==6222==
==6222== For counts of detected and suppressed errors, rerun with: -v
==6222== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
fish: Process 6222, “valgrind” “echo franz | valgrind ./a.out” terminated by signal SIGSEGV (Address boundary error)
You can clearly see, that the crash happens in getLength, because it tries to access address 0x0. When you run this with gdb, you will stop at exactly that point and can see print textString, that it is 0 and not properly initiliazed.
Please read What is a debugger and how can it help me diagnose problems? for further information!
You are witnessing undefined behavior, due to strcpy(textString, textArray); writing out of bounds.
In
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength];
strcpy(textString, textArray);
cout << textString << endl;
}
strlen (textArray) returns the length of a null-terminated string pointed at by textArray. Such length doesn't include the null-terminator itself. However, strcpy writes the null-terminator to the destination string. To avoid such an issue, allocate a place for the null-terminator:
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength + 1];
strcpy(textString, textArray);
cout << textString << endl;
}
I am assuming that textLengthand textString are member variables of your class (of type size_t and char * respectively). You don't show the definition of your class Text.
You made a mistake in your constructor. This line
char* textString = new char[textLength];
should be
char* textString = new char[textLength+1];
to allow for the trailing '\0' that C strings have. Also you might want to bulletproof your class Text by making sure your write a copy contructor, destructor and assignment operator. Also consider what happens if NULL is passed to Text constructor. Alternatively a better option is to use std::string as a member variable, which means you can do away with the copy constructor, destructor and assignment operator (the compiler generated versions will just work); you can also do away with textLength and you can write a constructor that is member initialised.
For some reason Valgrind seems to give an invalid write at a line where the ifstream.read is called (in the searchInFile function). gdb seems to segfault at the same line but I can't figure out the problem. If a read function is being called, how is there a write operation taking place?
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#define FILENAME "./test.dat"
using namespace std;
struct record
{
long long int phoneNumber;
char name[10];
char address[75];
};
int searchInFile(long long int phoneNo)
{
/*
Search if a record with the given phone no.
exists in the file. Returns the number of
records before the required record. Returns
-1 if no such record exists.
*/
int ctr = 0;
record * buffer = NULL;
ifstream file(FILENAME, ios::binary);
while(file.read( reinterpret_cast<char*>(buffer), sizeof(record)))
{
if(buffer->phoneNumber == phoneNo)
{
file.close();
return(ctr);
}
ctr++;
}
file.close();
if(buffer->phoneNumber == phoneNo)
return(ctr);
return(-1);
}
void displayRecord(long long int phoneNo)
{
/*
Displays the record with given phone no.
*/
int location = searchInFile(phoneNo);
record * buffer = NULL;
if(location == -1)
cout << "Invalid Number! No such record exists!" << endl;
else
{
ifstream file(FILENAME, ios::binary);
cout << "Reading Error Code: " << file.read(reinterpret_cast<char*>(buffer), sizeof(record));
cout << "Phone Number: " << buffer->phoneNumber << endl;
cout << "Name: " << buffer->name << endl;
cout << "Address: " << buffer->address << endl;
file.close();
}
}
void saveRecord(record toSave)
{
/*
Saves a new record to file
*/
ofstream ofile(FILENAME, ios::app | ios::binary);
//ofile.seekp(0, ios::end);
ofile.write( reinterpret_cast<char*>(&toSave), sizeof(record));
ofile.close();
}
int main()
{
record test = {(long long int)9988776655, "Debug", "Address of Debugger"};
saveRecord(test);
displayRecord((long long int) 9988776655);
return(0);
}
Here is the Valgrind and gdb output for it:
Syscall param write(buf) points to uninitialised byte(s)
at 0x543B870: __write_nocancel (syscall-template.S:81)
by 0x4EB18D5: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE9A77: std::basic_filebuf<char, std::char_traits<char> >::_M_convert_to_external(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EEA4D2: std::basic_filebuf<char, std::char_traits<char> >::overflow(int) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE9CA2: std::basic_filebuf<char, std::char_traits<char> >::_M_terminate_output() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE9D4A: std::basic_filebuf<char, std::char_traits<char> >::close() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EEBB4C: std::basic_ofstream<char, std::char_traits<char> >::close() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4011A5: saveRecord(record) (test.cpp:84)
by 0x4012F1: main (test.cpp:91)
Address 0x5a1b31d is 93 bytes inside a block of size 8,192 alloc'd
at 0x4C2B8A8: operator new[](unsigned long) (vg_replace_malloc.c:423)
by 0x4EE98AB: std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE9EC1: std::basic_filebuf<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EEB747: std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(char const*, std::_Ios_Openmode) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x40117E: saveRecord(record) (test.cpp:81)
by 0x4012F1: main (test.cpp:91)
Invalid write of size 1
at 0x4ED338E: std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE8D0D: std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EB4CAA: std::istream::read(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x400EDD: searchInFile(long long) (test.cpp:30)
by 0x400FAA: displayRecord(long long) (test.cpp:55)
by 0x401300: main (test.cpp:92)
Address 0x0 is not stack'd, malloc'd or (recently) free'd
Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0x0
at 0x4ED338E: std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EE8D0D: std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x4EB4CAA: std::istream::read(char*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
by 0x400EDD: searchInFile(long long) (test.cpp:30)
by 0x400FAA: displayRecord(long long) (test.cpp:55)
by 0x401300: main (test.cpp:92)
If you believe this happened as a result of a stack
overflow in your program's main thread (unlikely but
possible), you can try to increase the size of the
main thread stack using the --main-stacksize= flag.
The main thread stack size used in this run was 8388608.
HEAP SUMMARY:
in use at exit: 8,760 bytes in 2 blocks
total heap usage: 4 allocs, 2 frees, 17,520 bytes allocated
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 8,760 bytes in 2 blocks
suppressed: 0 bytes in 0 blocks
ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Note that the test.dat file was deleted before each run.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b7338e in std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7b7338e in std::basic_streambuf<char, std::char_traits<char> >::xsgetn(char*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff7b88d0e in std::basic_filebuf<char, std::char_traits<char> >::xsgetn(char*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff7b54cab in std::istream::read(char*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x0000000000400ede in searchInFile (phoneNo=9988776655) at test.cpp:30
#4 0x0000000000400fab in displayRecord (phoneNo=9988776655) at test.cpp:55
#5 0x0000000000401301 in main () at test.cpp:92
The only thing I can think of is that buffer is being written into over here, but that doesn't get me anywhere.
The read() method is writing the information it has read into your buffer,
and I suspect valgrind thinks this write is invalid,
so start looking at how your buffer is allocated.
In this case valgrind is clearly correct. You need to allocate memory to buffer for it to put the file contents into.
eg
record * buffer = new record;
buffer is null. you do not allocate any storage to read into it, passing wrong size (it should be 0, not sizeof(record)) and dereference it later causing Undefined Behavior. write and read in valgrind refer to memory access, not to file read or write.
I am having a bizarre error in assigning values in an array of strings. It assigns two or three intermittently and then crashes.
I am trying to implement a simple unsorted dictionary like structure using two parallel arrays(one of strings and one of integers)
Here is where in the code I think the fault is occurring.
std::ifstream infile1("out1.tmp");
std::string word;
while (getline(infile1,word)){
std::istringstream iss(word);
printf("stream created\n");
if (!(iss >> bookone.keys[i]))
break;
i++;
}
bookone is a dictionary object that has the public fields:keys and index. Even if I move the variable assignment into the class it errors in the same way.
The part that confuses me the most is that it appears to work the first few iterations.
strace provides this:
open("out1.tmp", O_RDONLY) = 5
read(5, "This\nEtext\nfile\nis\npresented\nby\n"..., 8191) = 8191
write(1, "stream created\n", 15stream created
) = 15
write(1, "stream created\n", 15stream created
) = 15
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xd36ff8} ---
+++ killed by SIGSEGV +++
[1] 16430 segmentation fault strace ./book macbeth.txt othello.txt
and valgrind gives me a bunch of these:
==16499== Invalid read of size 8
==16499== at 0x4EAB634: std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.20)
==16499== by 0x401673: main (in /home/luna/sauce/books/book)
==16499== Address 0x5a00ca8 is 24 bytes before a block of size 568 alloc'd
==16499== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==16499== by 0x56C106C: __fopen_internal (iofopen.c:73)
==16499== by 0x401555: main (in /home/luna/sauce/books/book)