I have a c++ class that roughly looks like this (see code below). It has an input buffer and an output buffer using a std::stringbuf. Because I also want access to the raw buffer, I set the underlying buffer with my own user-defined byte array using std::stringbuf.pubsetbuf().
All things seem to work fine, until I no longer need the object but when the object is destructed, it causes my program to crash with an access violation.
I traced it down to the piece of code as illustrated below. It looks to me that the stringbuf is somehow cleaning up my user-defined byte array itself?? My program doesn't crash when I remove the code in the destrcutor of my class to free the byte array I previously allocated in the constructor.
Any advice on this, please? Am I wrongly using the std::stringbuf? I'm using the Borland 5.0 compiler (I know it's a very old and outdated compiler, but I have to stick to this compiler for a while).
class SomeClass {
private:
char *mIBuf;
char *mOBuf;
std::stringbuf mIBufStream;
std::stringbuf mOBufStream;
public:
SomeClass(int iBufSize, int oBufSize) :
mIBuf(), mOBuf(),
mIBufStream(), mOBufStream()
{
mIBuf = (char*)malloc(iBufSize);
mOBuf = (char*)malloc(oBufSize);
mIBufStream.pubsetbuf(mIBuf, iBufSize);
mIBufStream.pubseekpos(0);
mOBufStream.pubsetbuf(mOBuf, oBufSize);
mOBufStream.pubseekpos(0);
}
virtual ~SomeClass()
{
free(mIBuf);
free(mOBuf)
}
};
According to the Standard stringbuf doesn't have a destructor of its own and streambuf's destructor does nothing. Your old compiler and library may or may not be following that; the evidence is that it isn't.
Well, in principle you are doing something wrong. When you call pubsetbuf you are giving that object permission to use that buffer for as long as the object lives, or until you change its buffer again.
Looking at your destructor, you aren't keeping your side of the bargain.
virtual ~SomeClass()
{
free(mIBuf);
free(mOBuf); // <- missing semicolon in your code
// the stringbuf objects are still alive here
} // they get automatically destroyed here
One option is to arrange for the stringbuf objects to be destroyed before you free the buffers (char* buffer deallocation will need to be done by a helper class, either a base class or a member declared before the stringbuf -- std::vector<char> would be a good choice).
Or, you can let the stringbuf know that you're revoking its permission to use your memory:
virtual ~SomeClass()
{
mIBufStream.pubsetbuf(0, 0);
mOBufStream.pubsetbuf(0, 0);
// the stringbufs cannot use your memory any longer
free(mIBuf);
free(mOBuf);
}
Well, to answer my own question... (and thanks to Ben Voight for his useful advise). Until someone else would prove me wrong, I've come to the conclusion that my issue is implementation specific and that the Borland 5.0 STL library may not be conform the standard.
I tested my sample class. I extracted it and put it in a small test program as listed below (no other code that would possibly corrupt the memory). I compiled 1 version with Visual Studio 2013, the other with Borland 5.0. The one compiled with Visual Studio runs just fine. The one compiled with Borland crashes after the 1st iteration.
#include <iostream>
include
class SomeClass {
char *mIBuf;
char *mOBuf;
std::stringbuf mIBufStream;
std::stringbuf mOBufStream;
public:
SomeClass(int iBufSize, int oBufSize) : mIBuf(NULL), mOBuf(NULL), mIBufStream(), mOBufStream() {
mIBuf = (char*)malloc(iBufSize);
mOBuf = (char*)malloc(oBufSize);
mIBufStream.pubsetbuf(mIBuf, iBufSize);
mIBufStream.pubseekpos(0);
mOBufStream.pubsetbuf(mOBuf, oBufSize);
mOBufStream.pubseekpos(0);
}
virtual ~SomeClass() {
mIBufStream.pubsetbuf(0, 0);
mOBufStream.pubsetbuf(0, 0);
free(mIBuf);
free(mOBuf);
}
};
int main(int argc, char* argv[])
{
for (int x = 0; x < 1000; x++) {
SomeClass SomeClass(128 * 1024, 128 * 1024);
std::cout << "Pass " << x + 1 << std::endl;
}
return 0;
}
Related
I was running a little experiment to better understand when constructors/destructors are implicitly called, and I discovered something really strange.
The following code invokes the default copy constructor when myFunction() is called. Before exiting the scope of myFunction(), my user-defined ~myClass() is invoked, which should be calling free() on dangerData. However, this doesn't seem to be freeing dangerData!
#include <cstdio>
#include <cstdlib>
class myClass {
static int nextid;
int myID;
char *dangerData;
public:
myClass() {
myID = nextid++;
printf("Constructing myClass number %d\n", myID);
dangerData = (char *)malloc(1024);
dangerData[12] = 0;
}
~myClass() {
printf("Destructing myClass number %d. dangerData = %p\n", myID, (void *) dangerData);
dangerData[12] = 'a'; //Mark the array
free(dangerData); //This call chould free the array... but it doesn't!
}
void msg() {
printf("Message from myClass number %d. dangerData[12] = %d\n", myID, dangerData[12]);
}
};
int myClass::nextid = 1;
void myFunction(myClass param) {
param.msg();
}
int main() {
myClass m;
myFunction(m); //Calls default copy constructor
m.msg();
return 0;
}
The output from this code is:
Constructing myClass number 1
Message from myClass number 1. dangerData[12] = 0
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 0
Message from myClass number 1. dangerData[12] = 97
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 97
The first call to the desctructor is definitely calling free() on the malloc'd array, however the call to m.msg() in main() can still access it without segfaulting!
Is this supposed to be happening?
Is this supposed to be happening?
Nothing particular is "supposed" or rather "expected" to happen here - you are invoking undefined behavior, so anything could happen, including "nothing".
the call to m.msg() in main() can still access it without segfaulting!
This is not terribly surprising (but again, nothing you should ever count on). Freeing the memory more or less tells the OS that that memory can be reused/overwritten freely. The more focus there is on speed over safety between your compiler, OS and their settings, the less work they will invest into marking this memory as inaccessible, and since you just used that exact memory location you would have to run under very stringent OS checks to even get a segfault there. It is also exceedingly unlikely for that 13th character to be overwritten in the time between the two msg() calls, so you are likely to read back the same thing again.
But all this just pertains to this small example and is, again, nothing to rely on. Undefined behavior (somewhat unfortunately) does not automatically mean "your program will segfault now". It may do, or it may segfault two minutes later in a completely different part, or silently output wrong results, or format your hard drive. Or it may run as you intended, this one time.
Problem: Getting an error when running my .exe
An unhandled exception of type 'System.AccessViolationException'
occurred in AddingWrapper.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
In the console it writes this:
Unhandled Exception: System.AccessViolationException : attempted to
read or write protected memory. This is often an indication that other
memory is corrupt. at gcroot (Add ^).. P$AAVAdd##(gcroot(Add^)) at
AddingWrapper.Adding(AddingWrapper, Int32* x, Int32* y)
Code snippet:
VB code:
Public Class Add
Public Function Adding(ByVal x As Double, ByVal y As Double) As Integer
Return x + y
End Function
End Class
AddingWrapper.h:
#pragma once
#include "stdafx.h"
class AddingWrapperPrivate;
class __declspec(dllexport) AddingWrapper {
private: AddingWrapperPrivate* _private;
public: AddingWrapper();
int Adding(int* x, int* y);
~AddingWrapper();
};
AddingWrapper.cpp
#include "stdafx.h"
#include "AddingWrapper.h"
#using "Class1.dll"
#include <msclr\auto_gcroot.h>
using namespace System::Runtime::InteropServices;
class AddingWrapperPrivate {
public: msclr::auto_gcroot<Add^> add;
};
AddingWrapper::AddingWrapper()
{
_private = new AddingWrapperPrivate();
_private->add = gcnew Add();
};
int AddingWrapper:: Adding(int* x, int* y) {
return _private->add->Adding(*x, *y);
};
AddingWrapper::~AddingWrapper()
{
delete _private;
};
calling code:
#include "stdafx.h"
#include "AddingWrapper.h"
#include <iostream>
int main()
{
int *a = 0;
int *b = 0;
AddingWrapper *add;
int results = add->Adding(a,b);
std::cout << "here is the result";
std::cout << results;
return 0;
}
Could it be due to my Class1.dll in AddingWrapper.cpp is using VB.net? Or it's a question of other issues? All the other threads seem to all differ in answer (i.e one is suggesting the user account doesn't have all the rights to the computer). If ever I missed on of those thread, please link it to me, this error is killing me
I should also add this error is at run time not compile time.
In the main function, you are using a "null" object pointer and passing in NULL pointers - that will cause the error you are seeing.
int main()
{
int a = 1;
// ^^^ remove the pointer (and give it a "interesting" value)
int b = 2;
// ^^^ remove the pointer
AddingWrapper add; // remove the pointer (or allocate with new)
// ^^^ remove the pointer
int results = add.Adding(&a, &b); // pass in the address of the integers
// ^^^ syntax change
std::cout << "here is the result";
std::cout << results;
return 0;
}
The variable a, b and add where only pointers, pointing to nothing; this causes access violations. Changing them to be automatic objects ("on the stack") will fix this. If dynamic objects are needed, you can new them (and delete them afterwards); but favour library utilities such as std::shared_ptr and std::unique_ptr etc. to help manage the lifetime of the object.
Several things:
You haven't shown your VB code. Since you've written an unmanaged class, not a managed one, it seems likely that either the import is not correct, or that you're passing a bad pointer.
Why are you passing an int* to the wrapper, only to dereference it right there? Why not pass an int?
You're in C++/CLI, why are you not writing a managed class? You wouldn't need auto_gcroot, and you don't need to deal with DLL imports/exports: VB.Net would be able to see your class the same as it can see any .Net class, and reference it just as easily as you can reference any .Net library.
Edit
OK, it wasn't obvious that you were trying to call some VB.Net code from C++. I thought you were trying to go the other direction.
The problem is almost certainly that you're passing a bad pointer to AddingWrapper::Adding.
You don't need to pass a pointer for basic data types, so you can get rid of that entire thing if you want. The fact that it's a double in VB but an int in C++ is fine, C++/CLI knows that the VB code takes a double and will convert appropriately.
Also, note that you're not passing a pointer between managed and unmanaged code. You're passing a pointer from one unmanaged class to another unmanaged class (whatever calls AddWrapper, to AddWrapper), but across the managed/unmanaged border, you're passing a plain old int.
Let's me describe my problem. I've analyzed the following code generated with Visual Studio 2015 [Release] with OllyDbg and memset is called twice (once with 408 bytes, and latter with 400 bytes). Clearly the 408 bytes is the compiler doing a zero initialization on my class.
Why is this happening?
My mainclass has already a constructor which should get rid of the compiler generated constructor.
The funny thing is: If I remove the member "someotherclas sb" from the mainclass, m_buffer will only be set once (by me, with 400 bytes).
// ConsoleApplication.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
class someotherclas
{
public:
int * ptr;
};
class mainclass
{
public:
char m_buffer[400];
someotherclas sb; //If I remove this, buffer will be memset once only (by me, in the constructor)
int a;
mainclass()
{
memset(m_buffer, 0x00, sizeof(m_buffer));
a = 6;
}
};
int main(int argc, char * arr[])
{
mainclass * buffer2 = new mainclass;
return 0;
}
I guess this happens because Security Development Lifecycle checks are enabled for your project. Could you check the compiler options? If so, the following applies:
When /sdl is enabled, the compiler ... Performs class member
initialization. Automatically initializes all class members to zero on
object instantiation (before the constructor runs). This helps prevent
the use of uninitialized data associated with class members that the
constructor does not explicitly initialize.
So this is the situation.
I have a class
Class L_FullQuote
{
private:
vector<int> time;
..
}
and
Class B
{
L_FullQuote *Symbols[100];
void handle message()
}
Inside handle msg
i have this statement
Symbols[i]->time.push_back(2);
the code builds fine..but when i use the generated dll. the application just crashes..sometimes it takes me to a nxt poiner error in vector..but mostly the whole application just crashes.
It works fine without that line.
Please help
Thanks
You're already using vector, so why not take it one step further? Using std::vector will allow you to focus on writing your functionality, rather than worrying about memory management.
This example differs slightly from what you originally posted. Your original question class B has an array of 100 pointers that each must be initialized. In the example below, we create a std::vector of L_FullQuote objects that is initially sized to 100 objects in the constructor.
class L_FullQuote
{
public:
vector<int> time;
};
class B
{
public:
// Initialize Symbols with 100 L_FullQuote objects
B() : Symbols(100)
{
}
std::vector<L_FullQuote> Symbols;
void handle_message()
{
Symbols[i].time.push_back(2);
// other stuff...
}
};
L_FullQuote *Symbols[100];
Here you declare an array of pointer to L_FullQuote, but you never initialize any of the pointers, so when you call:
Symbols[i]->...
You are dereferencing an invalid pointer. Also note that you have declared time as private (though your code wouldn't even compile this way, s B as a friend of A I assume?)
Simply declaring an array of pointers does not initialize each element to point to a valid object. You need to initialize each one, something like:
for(int i = 0; i < 100; ++i) {
Symbols[i] = new L_FullQuote();
}
Only then do you have an array full of valid pointers. Don't forget to deallocate them though!
time is private member of class L_FullQuote, from class B you don't have access to that field
I have the following structure:
struct CountCarrier
{
int *CurrCount;
};
And this is what I want to do:
int main()
{
CountCarrier carrier = CountCarrier();
*(carrier.CurrCount) = 2; // initialize the *(carrier.CurrCount) to 2
IncreaseCount(&carrier); // should increase the *(carrier.CurrCount) to 3
}
void IncreaseCount(CountCarrier *countCarrier)
{
int *currCounts = countCarrier->CurrCount;
(*currCounts)++;
}
So, my intention is specified in the comments.
However, I couldn't get this to work. For starters, the program throws an exception at this line:
*(carrier.CurrCount) = 2;
And I suspect the following line won't work as well. Anything I did wrong?
struct CountCarrier
{
int *CurrCount; //No memory assigned
};
You need to allocate some valid memory to the pointer inside the structure to be able to put data in this.
Unless you do so, What you ar trying to do is attempting to write at some invalid address, which results in an Undefined Behavior, which luckiy in this case shows up as an exception.
Resolution:
struct CountCarrier
{
int *CurrCount; //No memory assigned
CountCarrier():CurrCount(new(int))
{
}
};
Suggestion:
Stay away from dynamic allocations as long as you can.
When you think of using pointers always think whether you really need one. In this case it doesn't really seem that you need one, A simple int member would be just fine.
You need to create the pointer. ie. carrier->CurrCount = new int;
*(carrier.CurrCount)
This is dereferencing the pointer carrier.CurrCount, but you never initialized it. I suspect this is what you want:
carrier.CurrCount = new int(2);
I seriously doubt that your program throws an exception at the line:
*(carrier.CurrCount) = 2;
While throwing an exception is certainly allowed behaviour, it seems much more likely that you encountered an access violation that caused the process to be killed by the operating system.
The problem is that you are using a pointer, but your pointer is not initialised to point at anything. This means that the result of the pointer dereference is undefined.
In this situation there does not seem to be any advantage to using a pointer at all. Your CurrCount member would work just as well if it was just a plain int.
If you are using C++, then you should encash its facilities. Instead of correcting your code, I am showing here that how the code should look like:
struct CountCarrier
{
int CurrCount; // simple data member
CountCarrier(int count) : CurrCount(count) {} // constructor
CountCarrier& operator ++ () // overloaded operator
{
++ CurrCount;
return *this;
}
};
We are overloading operator ++, because you have only one data member. You can replace with some named method also, like void IncrementCount().
CountCarrier carrier(2);
++ carrier;
As Als said, you need to provide some memory for the code to work.
But why make it so complicated? You don't need any pointers for the code you have to work. The "modern C++" way looks more like this:
struct CountCarrier
{
public:
CountCarrier(int currCount) : currCount(currCount) {}
void IncreaseCount() { ++currCount; }
int GetCount() const { return currCount; }
private:
int currCount;
};
int main()
{
CountCarrier carrier(2); // Initialize carrier.currCount to 2
carrier.IncreaseCount(); // Increment carrier.currCount to 3
}
Note how much cleaner and less error prone that is. Like I said, pick up a good introductory C++ book and read through it.