This is the function which I read data from micro, but why when I allocate buffer by call new, the application crash, if I use malloc, it ok
void AlsaMicrophoneWrapper::readThreadFunction()
{
int bufSize = m_bitsPerFrame * m_frames;
// char *buf = new char(bufSize);//crash
char *buf = (char *)malloc(bufSize);
if (NULL == buf)
{
printf("Snd_ReadThread allocate mem error\n");
return;
}
snd_pcm_sframes_t retFrame;
ssize_t returnCode;
while (true)
{
retFrame = snd_pcm_readi(m_pcmHandle, buf, m_frames);
if (-EPIPE == retFrame)
{
snd_pcm_prepare(m_pcmHandle);
}
else if (retFrame > 0)
{
returnCode = m_writer->write(buf, retFrame);
if (returnCode <= 0)
{
printf("Failed to write to stream.\n");
}
}
}
free (buf);
return;
}
new char(bufSize) allocates a single char and initializes it to bufSize. You want new char[bufSize]. And when you new[] something, you must delete[] it later, not free it.
char *buf = new char[bufSize];
...
delete[] buf;
To avoid having to manage memory manually, you could use std::unique_ptr or std::vector.
auto buf = std::make_unique<char[]>(bufSize);
// use buf.get() to access the allocated memory
Or
std::vector<char> buf(bufSize);
// use buf.data() to access the allocated memory
Related
The following code shows me getting the filesize of a certain file to then later on make a large enough buffer to ensure I can store all the files content in this buffer. So what I did was allocating it on the heap, because I couldn't know if the file is huge or not etc.
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
size_t filesize(FILE* f) {
size_t size;
fseek(f, 0L, SEEK_END);
size = ftell(f);
fseek(f, 0L, SEEK_SET);
return size;
}
char* read_file(std::string name) {
FILE* f;
fopen_s(&f, name.c_str(), "rb");
size_t size = filesize(f);
char* buffer = new char[size+1];
memset(buffer, 0, size+1);
fread(buffer, sizeof(char), size+1, f);
fclose(f);
return buffer; //this is the buffer with the content to send
}
int main() {
char* buffer = read_file("main.cpp");
printf("%s", buffer);
delete[] buffer;
buffer = nullptr;
getchar();
return 0;
}
My question is, have I successfully deleted
char* buffer = new char[size+1];
from the heap by doing this:
char* buffer = read_file("main.cpp");
delete[] buffer;
buffer = nullptr;
Or does it still remain somewhere?
And if it does, how would I pin-point it and delete it?
Any other tips on how to handle raw pointers are appreciated as well.
Yes your code is correctly deleting the buffer.
C++ has various ways to handle this for you though so you don't need to worry about it and will be less likely to make mistakes and forget to free the buffer in some or all code paths, e.g. its easy to make mistakes like this:
int main()
{
char* buffer = read_file("main.cpp");
if ( buffer[0] != 'A' )
{
std::cout << "data is invalid\n";
return 1; // oops forgot to free buffer
}
delete[] buffer;
// data is valid
return 0;
}
One option is to use std::unique_ptr which will free the buffer for you when it goes out of scope:
#include <memory>
#include <string>
#include <iostream>
std::unique_ptr<char[]> read_file(std::string name) {
....
std::unique_ptr<char[]> buffer(new char[size+1]);
....
return buffer;
}
int main()
{
std::unique_ptr<char[]> buffer = read_file("main.cpp");
if ( buffer[0] != 'A' )
{
std::cout << "data is invalid\n";
return 1; // buffer is freed automatically
}
buffer.reset(); // can manually free if we are finished with buffer before it goes out of scope
// data is valid
return 0;
}
Consider the following code please, including two threads buffering_thread (fills up buffer pointer with one message) and sending_thread (empties the buffer):
#include "msg.cpp"
msg * buffer= NULL;
byte * send_bytes= NULL;
bool keep_buffering = true;
bool keep_sending = true;
int counter = 0;
void start_buffering() {
while (keep_buffering){
while (buffer != NULL && keep_buffering){}
msg m (counter);
buffer = &m;
counter ++;
}
std::cout << "Finished start_buffering" << std::endl;
}
void sending() {
while (keep_sending){
if (counter > 10){
keep_buffering = false;
break;
}
if (buffer != NULL){
HeaderType messageHeader = buffer -> getHeader();
print(messageHeader);
send_bytes = (byte *) realloc(send_bytes,DATASIZE + HEADER);
memcpy (send_bytes, &messageHeader, HEADER);
memcpy (send_bytes + HEADER,buffer -> getText(), DATASIZE);
// Do something, suppose for now NOTHING
free (buffer -> getText());
buffer = NULL;
}
}
std::cout << "Finished sending" << std::endl;
}
int main () {
std::thread sending_thread(sending);
std::thread buffering_thread(start_buffering);
buffering_thread.join();
keep_sending = false;
sending_thread.join();
//free (buffer);
free (send_bytes);
return 0;
}
where the class msg is as follows:
#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <mutex>
#include <thread>
#define DATASIZE 10
#define HEADER sizeof(HeaderType)
class msg
{
private:
HeaderType header;
byte * text;
public:
msg(int ID);
HeaderType getHeader();
byte * getText();
};
msg::msg(int ID){
header.mID = ID;
text = (byte *)malloc (DATASIZE);
memset (text, '.', DATASIZE);
}
HeaderType msg::getHeader(){
return header;
}
void print(HeaderType header) {
std::cout << "Message ID: " << header.mID << std::endl;
}
byte * msg::getText(){
return text;
}
and this is HeaderType:
typedef struct {
int mID;
}HeaderType;
Valgrind reports:
==3809== 20 bytes in 2 blocks are definitely lost in loss record 1 of 1
==3809== at 0x4028876: malloc (vg_replace_malloc.c:236)
==3809== by 0x80492BD: msg::msg(int) (in /home/linux/LCR-write/src/test)
==3809== by 0x8049384: start_buffering() (in /home/linux/LCR-write/src/test)
Indeed, I guess there must not be any memory leak inside this code. The buffer should always be emptied by sending_thread. Would somebody point out the fault please.
The problem is in the start_buffering() function.
while (keep_buffering){
msg m (counter);
while (buffer != NULL && keep_buffering){}
buffer = &m;
counter ++;
}
This loop creates a msg and allocates the memory for text in it's constructor. Then it waits, and then it will do:
buffer = &m;
counter ++;
// end of loop
msg m (counter);
When the loop reaches the end, it starts the next iteration without waiting for anything. The 'old' msg m falls out of scope, and a new msg m is allocated at the exact same place on the stack than the old one. So the pointer buffer is still 'valid' (not really!), pointing to the new m. The result is a memory leak for the first msg m, and, more importantly, undefined behaviour. You may not use things that are not in scope anymore.
Additionally, I would recommend to use 'official' synchronisation and wait mechanisms.
you need a destructor for msg that frees the memory allocated for text in the constructor
class msg
{
private:
HeaderType header;
byte * text;
public:
msg(int ID);
HeaderType getHeader();
byte * getText();
~msg() {free(text);}
};
First off, this is running on OSX, compiled in xcode. I have tried both clang and g++, both show the same symptoms. Basically, there are two lines in this sample, one allocates and frees a buffer in the worker thread, and the other allocates the buffer in the main thread, and frees it in the worker thread. The in-thread alloc works fine, but the cross thread alloc causes the total memory used by the process (viewed using top) to increase by 4k bytes every time the buffer is retrieved on the worker thread. What gives here? The heap should be global to all threads in the process and no marshaling should be occuring here, so why is the process memory increasing?
Valgrind reports no leaks in both cases, and reports the same number of allocations and frees in both cases. However, the process memory is clearly increasing in one versus the other.
The sample code is stripped down to show the basics:
#include <iostream>
#include <stdio.h>
#include <list>
#include <assert.h>
#include <unistd.h>
class CNetworkBuffer
{
public:
uint32_t MaxSize;
uint32_t Size;
uint8_t *Data;
CNetworkBuffer()
{
printf("Creating new network buffer: %d %d\n", 0, 0);
Size = 0;
MaxSize = 0;
Data = NULL;
}
CNetworkBuffer(uint32_t size, uint32_t maxSize)
{
printf("Creating new network buffer: %d %d\n", size, maxSize);
MaxSize = maxSize;
Size = size;
Data = new uint8_t[MaxSize];
}
~CNetworkBuffer()
{
printf("Deleting network buffer of size %d (%d) %p\n", Size, MaxSize, Data);
if(Data != NULL)
{
delete[] Data;
Data = NULL;
}
}
};
class CNetworkBuffers
{
public:
//
// Public constructor
//
CNetworkBuffers()
{
}
//
// Public destructor
//
~CNetworkBuffers()
{
while(!m_buffers.empty())
{
CNetworkBuffer *p = m_buffers.front();
m_buffers.pop_front();
delete p;
}
}
//
// Initializes the total number of buffers in this cache and the size of
// each buffer
//
void Initialize(uint32_t numBuffers, uint32_t bufferSize)
{
for(int i = 0; i < numBuffers; ++i)
{
m_buffers.push_back(new CNetworkBuffer(0, bufferSize));
}
}
//
// Retrieves a new buffer from the list of free buffers. This call blocks if there
// are no free buffers.
//
std::shared_ptr<CNetworkBuffer> GetBuffer()
{
m_cs.lock();
if(m_buffers.size() > 0)
{
CNetworkBuffer *pBuffer = m_buffers.front();
m_buffers.pop_front();
printf("Retrieving buffer: %p\n", pBuffer);
m_cs.Unlock();
return std::shared_ptr<CNetworkBuffer>(pBuffer);
}
else
{
assert(false);
}
m_cs.unlock();
}
private:
//
// The list of free buffers in this class.
//
std::list<CNetworkBuffer*> m_buffers;
std::mutex m_cs;
};
static void *
ThreadFunc(void *p)
{
CNetworkBuffers *buffers = (CNetworkBuffers *)p;
for(int i = 0; i < 64; ++i)
{
//
// NOTE: This type of allocation works fine
//
std::shared_ptr<CNetworkBuffer> buffer(new CNetworkBuffer(0, 1024));
//
// NOTE: Comment out the previous line and uncomment out this one,
// and watch as the process memory grows.
//
//std::shared_ptr<CNetworkBuffer> buffer = buffers->GetBuffer();
printf("Retrieved buffer of size %d (%d) - %d\n", buffer->Size, buffer->MaxSize, i);
sprintf((char *)buffer->Data, "%s", "DEADBEEF");
sleep(1);
}
return NULL;
}
int main(int argc, const char * argv[]) {
printf("Allocating memory for buffers\n");
CNetworkBuffers buffers;
buffers.Initialize(64, 1024);
// Now create another thread to read use those buffers
pthread_t t;
pthread_create(&t, NULL, ThreadFunc, &buffers);
pthread_join(t, NULL);
return 0;
}
I am trying to write a large binary file into a buffer in a C++ program. GDB always gets a segfault after trying to create a buffer the same size as the file read. It either fails on fclose(pf), rewind, or f(open) which leads me to believe that there is something wrong when I am trying to create the buffer. My code segment is as follows.
static int fileTransfer(struct mg_connection *conn, char * filename){
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
char buf[size];
fclose(fp);
// This is an attempt to stop a segment fault from rewind.
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(buf, 1, sizeof(buf), fp);
mg_send_data(conn, buf, n);
if(n < sizeof(buf) || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
return 1;
}
I have tried putting print statements in this code but they don't print to the console as they are running in a separate thread. Can someone give me some insight on why this segfault is happening, or some suggestions on how to make this code more efficient.
I should note that this code works properly on 1 and 10 MB files but not on anything larger.
never do this:
int size = ftell(fp);
char buf[size];
You are creating size on the STACK, not on the heap.... 100MB on the stack will not work.
AND... size must be a constant number, not a number coming from ftell(). I even don't know how it is compiling...
What you have to to is to allocate memory using malloc() or new operator.
static int fileTransfer(struct mg_connection *conn, char * filename){
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
char * buf = new char[size]; // fix also here!
fclose(fp);
// This is an attempt to stop a segment fault from rewind.
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(buf, 1, size, fp); // fix also here!
mg_send_data(conn, buf, n);
if(n < size || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
delete [] buf; // and you have to deallocate your buffer
return 1;
}
You are creating a buffer with automatic storage duration, which means it will be put on the stack by g++. The default stack size for any OS known to me is below 100 MB, meaning it will cause a segfault on system supporting them.
Try allocating your buffer with dynamic storage duration, which will place it on the heap.
What's going on is actually the namesake of this site! Basically, what is happening is your program is created it has a set amount of memory allocated for the stack.
When you create char buf[size], you are using a C99 feature called a variable length array (VLA). This allocates space on the stack for buf. However, buf is too large for the stack, so your program fails.
In order to fix this problem, you should use char * buf; and then do buf = malloc(size). This will place buf on the heap, which is larger than the stack. It also lets you check if you do not have enough memory, by checking if malloc() returns NULL. You need to be sure to free(buf) before you exit though!
As a side note, you can check how much space you have on the stack by using the ulimit -s command.
That seems like a lot to allocate on the stack. What if you put it on the heap instead?
char *buf = new char[size];
Use std::vector. Then you don't have the issues of stack space, or the other issue of writing non-standard C++ code:
#include <vector>
//...
static int fileTransfer(struct mg_connection *conn, char * filename)
{
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
std::vector<char> buf(size);
fclose(fp);
fp = fopen(filename, "r");
conn->connection_param = (void *) fp;
size_t n = 0;
if(fp != NULL)
{
n = fread(&buf[0], 1, buf.size(), fp);
mg_send_data(conn, &buf[0], n);
if(n < buf.size() || conn->wsbits != 0)
{
fclose(fp);
conn->connection_param = NULL;
}
}
return 1;
}
I have written a read function which reads values from serial port(LINUX) . It returns values as pointer to char . I am calling this function in another function and storing it again in a variable as pointer to char . I occasionally got stack over flow problem and not sure if this function is creating problem.
The sample is provided below. Please give some suggestions or criticism .
char *ReadToSerialPort( )
{
const int buffer_size = 1024;
char *buffer = (char *)malloc(buffer_size);
char *bufptr = buffer;
size_t iIn;
int iMax = buffer+buffer_size-bufptr;
if ( fd < 1 )
{
printf( "port is not open\n" );
// return -1;
}
iIn = read( fd, bufptr, iMax-1 );
if ( iIn < 0 )
{
if ( errno == EAGAIN )
{
printf( "The errror in READ" );
return 0; // assume that command generated no response
}
else
printf( "read error %d %s\n", errno, strerror(errno) );
}
else
{
// *bufptr = '\0';
bufptr[(int)iIn<iMax?iIn:iMax] = '\0';
if(bufptr != buffer)
return bufptr;
}
free(buffer);
return 0;
} // end ReadAdrPort
int ParseFunction(void)
{
// some other code
char *sResult;
if( ( sResult = ReadToSerialPort()) >= 0)
{
printf("Response is %s\n", sResult);
// code to store char in string and put into db .
}
}
Thanks and regards,
SamPrat
You do not deallocate the buffer. You need to make free after you finished working with it.
char * getData()
{
char *buf = (char *)malloc(255);
// Fill buffer
return buf;
}
void anotherFunc()
{
char *data = getData();
// Process data
free(data);
}
In your case I think you should free the buffer after printf:
if( ( sResult = ReadToSerialPort()) >= 0)
{
printf("Response is %s\n", sResult);
// code to store char in string and put into db .
free(sResult);
}
UPDATE Static buffer
Another option to use static buffers. It could increase performance a little bit, but getData method will be not a thread-safe.
char buff[1024];
char *getData()
{
// Write data to buff
return buff;
}
int main()
{
char *data = getData();
printf("%s", data);
}
UPDATE Some notes about your code
int iMax = buffer+buffer_size-bufptr; - iMax will always be 1024;
I do not see any idea of using bufptr since its value is the same as buffer and you do not change it anywhere in your function;
iIn = read( fd, bufptr, buffer_size-1 );
You can replace bufptr[(int)iIn<iMax?iIn:iMax] = '\0'; with bufptr[iIn] = '\0';
if(bufptr != buffer) is always false and this is why your pointer is incorrect and you always return 0;
Do not forget to free the buffer if errno == EAGAIN is true. Currently you just return 0 without free(buffer).
Good luck ;)
Elalfer is partially correct. You do free() your buffer, but not in every case.
For example, when you reach if ( errno == EAGAIN ) and it evaluates to true, you return without doing free on your buffer.
The best would be to pass the buffer as a parameter and make it obvious that the user must free the buffer, outside the function. (this is what basically Elalfer sais in his edited answer).
Just realized this is a C question, I blame SO filtering for this :D sorry! Disregard the following, I'm leaving it so that comments still make sense.
The correct solution should use std::vector<char>, that way the destructor handles memory deallocation for you at the end of scope.
what is the purpose of the second pointer?
char *buffer = (char *)malloc(buffer_size);
char *bufptr = buffer;
what is the purpose of this?
int iMax = buffer+buffer_size-bufptr; // eh?
What is the purpose of this?
bufptr[(int)iIn<iMax?iIn:iMax] = '\0'; // so you pass in 1023 (iMax - 1), it reads 1023, you've effectively corrupted the last byte.
I would start over, consider using std::vector<char>, something like:
std::vector<char> buffer(1500); // default constructs 1500 chars
int iRead = read(fd, &buffer[0], 1500);
// resize the buffer if valid
if (iRead > 0)
buffer.resize(iRead); // this logically trims the buffer so that the iterators begin/end are correct.
return buffer;
Then in your calling function, use the vector<char> and if you need a string, construct one from this: std::string foo(vect.begin(), vect.end()); etc.
When you are setting the null terminator "bufptr[(int)iIn
bufptr[iMax]=>bufptr[1024]=>one byte beyond your allocation since arrays start at 0.
Also int this case "int iMax = buffer+buffer_size-bufptr;" can be re-written as iMax = buffer_size. It makes the code less readable.