void Example1( char* ArrayA, unsigned int Length )
{
if( ArrayA == 0 )
{
ArrayA = new char[ Length + 1 ];
// Fill it with 2 - whatever
::memset( ArrayA, 0x02, sizeof( char ) * Length );
ArrayA[ Length ] = '0\n';
}
// Do whatever with ArrayA
// Clean-Up
// Error occurs
delete [ ] ArrayA;
};
void Example2( char* ArrayB, unsigned int Length )
{
bool IsDynamic = false;
if( ArrayB == 0 )
{
ArrayB = new char[ Length + 1 ];
// Fill it with 2 - whatever
::memset( ArrayB, 0x02, sizeof( char ) * Length );
ArrayB[ Length ] = '0\n';
IsDynamic = true;
}
// Do whatever with ArrayA
// Clean-Up
// Have to check...
if( IsDynamic )
delete [ ] ArrayB;
};
int main( void )
{
Example1( "\x01\x02\0x03", 3 ); // Example1 WILL NOT* declare ArrayA as a dynamic array - ERROR (caused by deleting non dynamic array)
Example2( 0, 3 ); // ArrayB will be a dynamic array - OK
Example1( 0, 3 ); // OK
Example2( "\x04\x05\0x06", 3 ); // ArrayB isn't a dynamic array - OK
return ( 0 );
};
The problem occurs when attempting to delete char* ArrayA in function Example1 because ArrayA is not a dynamic array. It will only be a dynamic array if it is equal to zero/null. So, to resolve that I created a similar function - Example2. The only difference is that Example2 has a boolean that checks to see if char* ArrayB is a dynamic array or not.
I know what I am doing is either incorrect or "noobish". So please help me. I will learn from my mistake.
How would you do it?
void Example3( char* ArrayC, unsigned int Length );
Maybe you could use this:
void Example2( char* ArrayB, unsigned int Length )
{
std::vector< char > internalArray;
if ( ArrayB != 0 )
{
internalArray.assign( ArrayB, ArrayB + Length );
}
else
{
internalArray.resize( Length, 0x2 );
}
// Do whatever with internalArray !!! <-------
// No (!!!) clenup need
};
I know what I am doing is either incorrect or "noobish". So please help me.
My overall recommendation would be to move from using C arrays to using std::vector instead.
Your example1 is definitely bad, since it tries to free an array that isn't dynamically allocated - that is NEVER right. As explained elsewhere, if you call across a DLL boundary, you may also have different allocators, so if the memory was not allocated where it is being deleted, things will go wrong. Let whoever allocated it delete it. Preferrably by using already existing standard functionality, such as std::vector
Your example2 only uses delete on something that was created within the function, which is perfectly fine. It doesn't try to delete something that it doesn't know is allocated in the same allocator. Yet, a std::vector would certainly be easier to handle.
Related
I need to violently write into a vector (to avoid superfluous memcpy).
Let's consider this very simplified piece of code
unsigned read_data ( char * buffer , unsigned maxsize )
{
const char * data = "Hi folks! I'm the data" ;
unsigned size = strlen( data ) ;
if (size > maxsize) return 0 ;
memcpy( buffer,data,size ) ;
return size ;
}
void main ()
{
std::vector<char> v ;
v.reserve( 50 ) ;
unsigned size = read_data( v.data(),v.capacity()) ;
v.force_actual_size( size ) ;
}
Here is the way I imagined : the data is actually written into the vector, but the vector's size is still 0.
So I need this force_actual_size method...
Is there a way implement it, or better, a clean way to do the same thing.
And of course, read_data comes from an old fashioned API I can't modify.
You can use std::vector::resize to allocate the memory you require and also correctly update the vector's size:
std::vector<char> v;
v.resize(50);
const auto new_size = read_data(v.data(), v.size());
v.resize(new_size);
First timer with allocator.
I am really struggling with a custom allocator.
I would say its obvious I don't know what I'm doing here.
My goal is to put all of the memory for the object in the process's heap.
I want the allocation to come from the system so its not language / runtime dependent.
I don't really want a struct, I just want:
std::list< WCHAR[SIZE], TestAllocator<WCHAR[SIZE]>> list;
or, I'd allocate the memory outside of the list and then just store a pointer to it
std::list< void*, TestAllocator<void*>> list;
But I don't see how to do it with non struct / classes. So I have a struct.
This thing crashes all over the place.
The code below that instantiates the list crashes, it doesn't even have to get to a list item creation / insert.
The allocator is used for the list creation before I attempt to add an item. (which I don't understand.) It seems to me that the allocator should only be used for the struct type I'm trying to add to the list. If the allocator is used to create the list and the items it holds how do I create the memory for the 2 different types, the list type and the list entry type?
Some other observations / questions.
When my list is created, it is placed at the memory address created:
OSAllocator::allocate count:[1] bytes each:[8][0x8] bytes total:[8][0x8]addr:[4305640][0x41B2E8]
OSAllocator::construct placement new:[4305640][0x41B2E8] sizeof(val):[8][0x8]
However, when my entry is created, it is placed 2 bytes past the address created:
OSAllocator::allocate count:[1] bytes each:[8200][0x2008] bytes total:[8200][0x2008] addr:[8837144][0x86D818]
OSAllocator::construct placement new:[8837152][0x86D820] sizeof(val):[8192][0x2000]
Is there an explanation for that?
Please help point out what I'm missing.
Thanks.
// allocator...
pointer allocate(size_type size, TestAllocator<void>::const_pointer hint = 0)
{
pointer p = (pointer)::HeapAlloc( ::GetProcessHeap(),
HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE,
size*sizeof(T) );
gCountAllocate++;
if( OSAllocatorConsole )
wprintf( L"OSAllocator::allocate: [%u][0x%X]\n", p, p );
return p;
}
size_type max_size() const throw() {return size_t(-1) / sizeof(value_type);}
void construct(pointer p, const T& val)
{
gCountConstructPlaceNew++;
if( OSAllocatorConsole )
wprintf( L"OSAllocator::construct placement new:[%u][0x%X]\n", p, p );
::CopyMemory( p, &val, sizeof(val) );
}
typedef struct _LogLine
{
WCHAR _logLine[4*1024];
} LOGLINE, *PLOGLINE;
DWORD TestAllocatorChar(int argc, WCHAR* argv[])
{
WCHAR buf[32] = {0};
DWORD total = 1;
std::list< LOGLINE, TestAllocator<LOGLINE>> list;
PLOGLINE pll = NULL;
LOGLINE ll = {0};
for(int i=0; i<total; i++ )
{
::StringCchPrintfW( ll._logLine, 4*1024, L"count:[%u]", i );
list.push_back( ll );
}
for( int i=0; i<total; i++ )
{
//pll = list.front();
wprintf( L"%s\n", list.front()._logLine );
wprintf( L"HeapFree item:[%u]\n", i );
//::HeapFree( ::GetProcessHeap(), HEAP_NO_SERIALIZE, p );
list.pop_front();
}
return 0;
}
This probably me being extremely tired, but I can't figure out how to copy part of a vector into a new vector.
What I am trying to do, is find inside an std::vector (where char is typedefed as byte) where the starting tag is, and copy the data from there, up to the closing tag (which is at the end, and is 7 chars long).
typedef char byte;
std::vector<byte> imagebytes;
std::vector<byte> bytearray_;
for ( unsigned int i = 0; i < bytearray_.size(); i++ )
{
if ( (i + 5) < (bytearray_.size()-7) )
{
std::string temp ( &bytearray_[i], 5 );
if ( temp == "<IMG>" )
{
// This is what isn't working
std::copy( std::vector<byte>::iterator( bytearray_.begin() + i + 5 ),
std::vector<byte>::iterator( bytearray_.end() - 7 )
std::back_inserter( imagebytes) );
}
}
}
I know this loop looks horrible, I am open to suggestions!
Please note, bytearray_ contains raw bytes of images, or audio files. Hence the vector.
The answer is simple: just copy, don't loop. The loop is already inside std::copy.
typedef char byte;
std::vector<byte> imagebytes;
std::vector<byte> bytearray_;
// Contents of bytearray_ is assigned here.
// Assume bytearray_ is long enough.
std::copy(bytearray_.begin() + 5,
bytearray_.end() - 7,
std::back_inserter( imagebytes) );
Instead of copying you can also construct a new vector directly from the existing one:
std::vector<byte> imagebytes(bytearray_.begin() + i + 5, bytearray_.end() - 7);
typedef struct pixel_type
{
unsigned char r;
unsigned char g;
unsigned char b;
} pixel;
buffer = (int *) malloc (sizeof(pixel) * stdin );
I keep getting an error that says "invalid operands to binary *(have unsigned int' and 'struct _IO_FILE *)." The struct is defined outside of a function so it is universal. The buffer is defined within the main. I can provide more code if needed. What is my problem?
EDIT: Alright so apparently I was a little confusing. What I'm trying to do is pass a file in, and then malloc enough space for that file. I was thinking of using a FILE function to pass the file in, and then using that, but was hoping to just use "stdin" instead. Is this not allowed? And this is in C. Just tagged C++ hoping someone else might see a similar problem.
Sorry for the silly question. Not new to C as a whole, but new to malloc. Second year student :P
I think you want to read the number of pixels from stdin:
int n;
scanf("%d", &n);
and then allocate memory for that many pixels:
unsigned char * buffer = (unsigned char *) malloc (sizeof(pixel) * n );
The right way to allocate the memory would be something like
size_t elements = 0;
... // get the number of elements as a separate operation
pixel *buffer = malloc( sizeof *buffer * elements ); // note no cast,
// operand of sizeof
if ( buffer )
{
// load your buffer here
}
In C, casting the result of malloc is considered bad practice1. It's unnecessary, since values of void * can be assigned to any pointer type, and under C89 compilers it can suppress a diagnostic if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope.
Also, since the expression *buffer has type pixel, the expression sizeof *buffer is equivalent to sizeof (pixel). This can save you some maintenance time if the type of buffer ever changes.
How you get the number of elements for your array really depends on your application. The easiest way would be to stick that value at the head of your data file:
size_t elements = 0;
FILE *data = fopen( "pixels.dat", "r" );
if ( !data )
{
// You will want to add real error handling here.
exit( 0 );
}
if ( fscanf( data, "%zu", &elements ) != 1 )
{
// You will want to add real error handling here
exit( 0 );
}
pixel *buffer = malloc( sizeof *buffer * elements );
if ( buffer )
{
for ( size_t i = 0; i < elements; i++ )
{
if ( fscanf( data, "%hhu %hhu %hhu", // %hhu for unsigned char
&buffer[i].r, &buffer[i].g, &buffer[i].b ) != 3 )
{
// more real error handling here
exit( 0 );
}
}
}
Naturally, this assumes that your data file is structured as rows of 3 integer values, like
10 20 30
40 50 60
etc.
1. As opposed to C++, where it's required, but if you're writing C++ you should be using the new operator anyway. Yes, you will see thousands of examples that include the cast. You will also see thousands of examples that use void main(). Most C references are simply crap.
// LED definitions for each step
static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t route1Step0LedsOff[] = { 0x26, 0xff };
static uint8_t route1Step1LedsOn[] = { 0x18, 0x45, 0x21, 0xff };
static uint8_t route1Step2LedsOn[] = { 0x56, 0x33, 0x42, 0x31, 0xff };
// First route (consisting of 3 steps + terminator).
static uint8_t* routeLeds1[][2] =
{
{ route1Step0LedsOff, route1Step0LedsOn },
{ NULL, route1Step0LedsOn },
{ NULL, route1Step0LedsOn },
{ NULL, NULL }
};
// Second route.
static uint8_t* routeLeds2[][2] =
{
// LED elements not shown, but similar to route 1.
{ NULL, NULL }
};
// Array of routes.
static ??? routes[] =
{
NULL,
routeLeds1,
routeLeds2,
NULL
};
I'm not sure of the correct type for routes[].
I'd like to know what the ??? should be?
I'm using a micro controller and MUST use arrays in order to force the arrays into flash memory instead of RAM.
You can't convert arrays to "pointers to pointers... to pointers" because they're dereferenced differently; trying to use a multidimensional array as a "pointer to... pointer" to something will cause undefined behaviour the same way dereferencing an invalid pointer would.
In memory, a "pointer to a pointer..." to an object is represented by
a -> b -> c -> ... -> object
Where a, b, c, ..., and object are in completely different parts of memory. To index a pointer, the pointer is dereferenced.
Arrays, however, are stored in a contiguous memory. For instance, int a[2][2] would be
[0,0][0,1][1,0][1,1]
Indexing a multidimensional array does not dereference a pointer, it changes the arithmetic that is used to calculate the offset from the beginning of the array that the desired value is at. The formula would be
address of array + index1 * sizeof(first dimension) + index2 * sizeof(second dimension) + ... + indexn * sizeof(object)
Where sizeof(nth dimension) is the size of all the subdimensions put together. For instance with int a[3][2] which is represented by
[0,0][0,1][1,0][1,1][2,0][2,1]
, the index a[2][1] would be
address of a + 2 * (sizeof(int) * 2) + 1 * sizeof(int)
Which, in C++, would be (char*)a + 16 + 4, the last element of the array.
To solve this problem, you need to use pointers only. You should not (and cannot) be storing multidimensional arrays alongside pointers in the same array.
I'm having a hard time putting this all into words; if I'm not making sense, please say so.
Try this:
typedef uint8* Array1; // first column/row
typedef Array1 Array2[2]; // uint* name[2]
typedef Array2* Array3; // get the idea?
// Array of routes.
static Array3 routes[] =
{
NULL,
routeLeds1,
routeLeds2,
NULL
};
Your problem is the multidimensional array:
If you need to go the array route, you can just add an extra step:
static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t* route1Step0[] = { NULL, route1Step0LedsOn };
static uint8_t** routeLeds1[] = { route1Step0 };
static uint8_t*** routes[] =
{
NULL,
routeLeds1,
NULL
};
If some of the arrays are fixed lengths, it may be possible to clean some of this up a little.
But IMO this is getting pretty ugly and could do with some real structs, rather than raw arrays.
If you're not tied to ussing arrays for some technical reason, you could change to use a structure like this: (Note if you're using C++11, then the constructors and construction can be made a lot nicer). You'll also need a make_vector helper, of which there are several floating around, if you want a nicer construction.
struct LedList
{
LedList( const std::vector<uint8_t> & v ) : leds( v ) {}
std::vector<uint8_t> leds;
};
struct LedStep
{
LedStep( const & LedList on_, const & LedList off_ ) : on_leds(on_), off_leds(off_) {}
RouteStepLedList on_leds;
RouteStepLedList off_leds;
};
struct LedRoute
{
LedRoute( const std::vector<LedStep> & steps_ ) : steps(steps_) {}
std::vector<LedStep> steps;
};
struct Route
{
Route( const std::vector<LedRoute> & routes_ ) : routes(routes_) {}
std::vector<LedRoute> routes;
};
//All routes
Route r( make_vector<LedRoute>()(
//First route
make_vector<LedStep>()(
//First step of first route
LedStep(
make_vector<uint8_t>()( 0x30 ),
make_vector<uint8_t>()( 0x26 )
) )(
//Second step of first route
LedStep(
make_vector<uint8_t>(),
make_vector<uint8_t>()( 0x18 )( 0x45 )( 0x21 )
) )(
//Third step of first route
LedStep(
make_vector<uint8_t>(),
make_vector<uint8_t>()( 0x56 )( 0x33 )( 0x42 )( 0x31 )
) ) ),
//Second route.
make_vector<LedStep>()(
//First step of second route
LedStep(
...
) ) (
//Second step of second route
...
);