Copying a MAT image to specific address in c++ - c++

I'm trying to copy a MAT image loaded in from a file to a specific address location. I have the following code
int main()
{
cv::Mat inImg = cv::imread("M6_traffic.jpg");
//Data point copy
unsigned char * pData = (unsigned char *)inImg.data;
unsigned char * Dest = (unsigned char *)0x0f000000;;
int width = inImg.rows;
int height = inImg.cols;
//data copy using memcpy function
memcpy(Dest, pData, sizeof(unsigned char)*width*height*3);
}
But when I run this it always crashes, any idea why? and is there a better why to do this? My end goal is to able to copy a image data to specific address in a Linux based system

propably there is no allocated memory on address 0x0f000000.
and you cannot force this to be a valid address
Allocate the right size of memory with malloc and it will work.
The OS then determines your address space and returns a pointer to it.
unsigned char* Dest = malloc(sizeof(pData));
memcpy(Dest, pData, sizeof(pData))

0x0f000000 is essentially a null pointer. What you're trying to do is copy data into a memory address that has not been set with memcpy(Dest, pData, sizeof(unsigned char)*width*height*3);.
You should allocate memory for Dest before your memcpy statement. You can do this with either malloc or calloc. These function calls are described in the following links. Hope this helps!
http://en.cppreference.com/w/c/memory/malloc
http://www.cplusplus.com/reference/cstdlib/calloc/

Related

Confusion with void* type memory allocation?

I am pretty inexperienced in C++ programming and now I'm trying to make a small program using dctmk to modify the pixel data of the dicom image. In doing so while reading documentation I found a c++ method about which I'm not quite clear. In the documention for the class DicomImage I found the following method:
int DicomImage::getOutputData ( void * buffer,
const unsigned long size,
const int bits = 0,
const unsigned long frame = 0,
const int planar = 0
)
My confusion is about buffer. It's quoted in the link as
buffer : pointer to memory buffer (must already be allocated)
Here my confusion is how do a I allocate? I'm not sure how I could allocate a memory that's a pointer of void type. Could you please explain. Thank you.
You can do it in the following way (for example):
void * mem = malloc(1024); // 1 kb
image.GetOutputData(mem, 1024);
// Don't forget to free(mem);
Another way:
char * mem = new char[1024];
image.GetOutputData((void *)mem, 1024);
// Don't forget to delete[] mem;
Another way:
char mem[1024];
image.GetOutputData((void *)&mem, 1024);
A pointer to void can point to anything, it's a generic nondescript anonymous pointer to some memory. This means that you can pass any kind of pointer as the first argument of the function, as all pointers can implicitly be converted to void*.
You can allocate any type of buffer. It will be converted using void*. However you will need to pass proper size of element. You will need to refer to documentation of api for size of each buffer element. In the example below it is 1 byte. And total buffer size is 10.
int size_of_buffer = 10;
unsigned char *buffer = malloc(sizeof(unsigned char)*size_of_buffer);
It looks like DicomImage::getOutputData does not care how you allocated your bytes. Simply take take the pointer to some blob of your choice (object, struct, array, whatever) and cast it to void*. You can get the memory with new, malloc or it can be a local variable.
Thing to be sure of:
Make sure you allocate enough space.
Make sure you accurately send the size parameter.
Make sure that you understand what format of data DicomImage::getOutputData works with.

Specifying the pointer when copying with OpenCV

I'm having an image memory that I stocked and saved it in a pointer to not loose its address.
I would like now to assign it to an IplImage by the following function memcpy (what I have tested):
IplImage* img=cvCreateImage(cvSize(640, 480), IPL_DEPTH_16U, 1);
VOID* ImgMem;
memcpy(img->imageData, ImgMemory, (640*480));
It really doesn't work. It stated Unhandled exception at 0x001b96dd in ex4.exe: 0xC0000005: Access violation reading location 0x00000044.
Any idea how to deal with that?
Your image is 640x480, but you copied 916x916 pixals.
There are two problems in your code. The first issue is you are not initializing 'ImgMem'.
VOID* ImgMem;
// ^^^^^^ Points to whatever
If you need to use a buffer prior to copying the data to the image buffer you need to allocate memory for it.
int bufferSize = 640*480*2;
char* ImgMem = new char[bufferSize];
Make sure that you delete the memory once you are done with it or you will end up leaking memory.
delete[] ImgMem;
A better alternative would be to use std::vector;
std::vector<char> ImgMem(bufferSize, 0);
memcpy(img->imageData, &ImgMem[0], ImgMem.size());
This way the memory is allocated, managed and freed by std::vector instead of you having to do it every time.
The second problem is you are trying to copy more memory into the image buffer than it can hold.
memcpy(img->imageData, ImgMemory, (916*916));
This will copy 839,056 bytes when img->imageData can only hold 307,200 bytes (assuming 8bpp).
[Edit: This answer does not take into account the attributes provided by the IplImage structure. This includes size AND alignment which are fairly important here in regards to memcpy. For more information on members of IplImage see here]
pixel type is unsigned short IPL_DEPTH_16U and it is 2 bytes, therefore you need to calculate total byte size accordingly:
int totalSize = 640*480*2;
char* ImgMemory = new char[totalSize];
memcpy(img->imageData, ImgMemory, (totalSize ));

Convert a string to and unsigned char []

I currently have a Packet set up like so:
struct Packet {
unsigned short sequenceNumber;
unsigned short length;
unsigned char control;
unsigned char ack;
unsigned short crc;
unsigned char data[];
Packet copy(const Packet& aPacket) {
sequenceNumber = aPacket.sequenceNumber;
length = aPacket.length;
control= aPacket.control;
ack = aPacket.ack;
crc = aPacket.crc;
memcpy (data, aPacket.data, aPacket.length);
}
};
This packet gets converted into a string for encryption and then needs to be taken from its decrypted string form back to a Packet. I am able to do this fine for all of the variables except for the unsigned char data[]. I have tried the following with no success:
string data = thePack.substr(pos, thePack.length()-pos);
unsigned char * cData = new unsigned char[data.length()];
strcpy((char *)cData, data.c_str());
memcpy(p.data, cData, data.length());
where data is the string representation of the data to be copied into the unsigned char [] and p is the Packet.
This gives the following from valgrind:
==16851== Invalid write of size 1
==16851== at 0x4A082E7: strcpy (mc_replace_strmem.c:303)
Even though it cites strcpy as the source, it compiles and runs fine with just the memcpy line commented out.
I have also tried replacing memcpy with strcpy with the same result. Any ideas? I feel that it might be due to the fact that data may have not been initialized and there for not have any memory allocated to it, but I thought memcpy would take care of this.
You haven't specified the size of the data array.
unsigned char data[];
This is legal, but rather difficult to use. The data array will follow the rest of the Packet structure in memory, but the compiler doesn't know how much space to allocate for it. So you have to allocate the extra space yourself:
size_t datalen = thePack.length()-pos;
void* pbuffer = malloc( sizeof (Packet) + datalen + 1 );
Packet* p = new (pbuffer) Packet;
memcpy(p.data, &thePack[pos], datalen);
p.data[datelen] = 0;
What won't work is letting the compiler decide how big a Packet should be, either using new Packet or a local variable Packet p;. That will end up with no space reserved for data. And no, memcpy doesn't allocate memory.
A much cleaner solution would be to use a std::vector for your variable-sized data array.
The char[] you're allocating is one character too small -- you must leave room for the NULL byte at the end:
unsigned char * cData = new unsigned char[data.length() + 1];
Use the strcpy version to copy the string, so the NULL byte gets copied correctly. Although it might run OK without that +1, there's no guarantee, and sometimes it might crash.

Proper Way To Initialize Unsigned Char*

What is the proper way to initialize unsigned char*? I am currently doing this:
unsigned char* tempBuffer;
tempBuffer = "";
Or should I be using memset(tempBuffer, 0, sizeof(tempBuffer)); ?
To "properly" initialize a pointer (unsigned char * as in your example), you need to do just a simple
unsigned char *tempBuffer = NULL;
If you want to initialize an array of unsigned chars, you can do either of following things:
unsigned char *tempBuffer = new unsigned char[1024]();
// and do not forget to delete it later
delete[] tempBuffer;
or
unsigned char tempBuffer[1024] = {};
I would also recommend to take a look at std::vector<unsigned char>, which you can initialize like this:
std::vector<unsigned char> tempBuffer(1024, 0);
The second method will leave you with a null pointer. Note that you aren't declaring any space for a buffer here, you're declaring a pointer to a buffer that must be created elsewhere. If you initialize it to "", that will make the pointer point to a static buffer with exactly one byte—the null terminator. If you want a buffer you can write characters into later, use Fred's array suggestion or something like malloc.
As it's a pointer, you either want to initialize it to NULL first like this:
unsigned char* tempBuffer = NULL;
unsigned char* tempBuffer = 0;
or assign an address of a variable, like so:
unsigned char c = 'c';
unsigned char* tempBuffer = &c;
EDIT:
If you wish to assign a string, this can be done as follows:
unsigned char myString [] = "This is my string";
unsigned char* tmpBuffer = &myString[0];
If you know the size of the buffer at compile time:
unsigned char buffer[SIZE] = {0};
For dynamically allocated buffers (buffers allocated during run-time or on the heap):
1.Prefer the new operator:
unsigned char * buffer = 0; // Pointer to a buffer, buffer not allocated.
buffer = new unsigned char [runtime_size];
2.Many solutions to "initialize" or fill with a simple value:
std::fill(buffer, buffer + runtime_size, 0); // Prefer to use STL
memset(buffer, 0, runtime_size);
for (i = 0; i < runtime_size; ++i) *buffer++ = 0; // Using a loop
3.The C language side provides allocation and initialization with one call.
However, the function does not call the object's constructors:
buffer = calloc(runtime_size, sizeof(unsigned char))
Note that this also sets all bits in the buffer to zero; you don't get a choice in the initial value.
It depends on what you want to achieve (e.g. do you ever want to modify the string). See e.g. http://c-faq.com/charstring/index.html for more details.
Note that if you declare a pointer to a string literal, it should be const, i.e.:
const unsigned char *tempBuffer = "";
If the plan is for it to be a buffer and you want to move it later to point to something, then initialise it to NULL until it really points somewhere to which you want to write, not an empty string.
unsigned char * tempBuffer = NULL;
std::vector< unsigned char > realBuffer( 1024 );
tempBuffer = &realBuffer[0]; // now it really points to writable memory
memcpy( tempBuffer, someStuff, someSizeThatFits );
The answer depends on what you inted to use the unsigned char for. A char is nothing else but a small integer, which is of size 8 bits on 99% of all implementations.
C happens to have some string support that fits well with char, but that doesn't limit the usage of char to strings.
The proper way to initialize a pointer depends on 1) its scope and 2) its intended use.
If the pointer is declared static, and/or declared at file scope, then ISO C/C++ guarantees that it is initialized to NULL. Programming style purists would still set it to NULL to keep their style consistent with local scope variables, but theoretically it is pointless to do so.
As for what to initialize it to... set it to NULL. Don't set it to point at "", because that will allocate a static dummy byte containing a null termination, which will become a tiny little static memory leak as soon as the pointer is assigned to something else.
One may question why you need to initialize it to anything at all in the first place. Just set it to something valid before using it. If you worry about using a pointer before giving it a valid value, you should get a proper static analyzer to find such simple bugs. Even most compilers will catch that bug and give you a warning.

Symbian panics when deleting dynamic array

I am trying to allocate a char array of size 1000. This array
is passed to a function where it should be filled with the data
that has been received from the TCP Socket. The problem occurs
then when I try to delete[] buffer: Here I get as a result a User
Panic 42. Unfortunately, I do not really see what is going wrong
in this simple code fragement...
int main
{
unsigned char *buffer = new unsigned char[1000];
Recv(&buffer);
delete[] buffer;
return (0);
}
void Recv(unsigned char **buffer)
{
TRequestStatus iStatus;
TSockXfrLength len;
TBuf8<1000> buff;
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
*buffer = ( unsigned char* )buff.Ptr();
}
Thanks for any useful hints!
What Konrad says is true, but I don't think he knows Symbian. If you do need a function to read bytes into a char buffer, then a better fix would be:
void Recv(unsigned char *aBuffer, int aSize)
{
TRequestStatus iStatus;
TSockXfrLength len;
TPtr8 buff(aBuffer, aSize);
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
}
TBuf8 is a descriptor which contains an array to hold the data. TPtr8 is a descriptor which refers to an external buffer that you specify. Either can be passed into RecvOneOrMore, since they both inherit from the parameter type, TDes8&. So the socket can be made to write its data directly into your buffer, instead of writing into a buffer on the stack and then copying as Konrad's code does.
You probably also need to check the status to detect errors, and report success/failure and the length written back to the caller.
Your array allocation is without effect because inside the function, you assign a new pointer to the array:
*buffer = ( unsigned char* )buff.Ptr();
Now the buffer points to another memory location, presumably one that you may not free using delete (e.g. one on the stack, or allocated using something other than new).
To fix the problem, it's probably best to copy the data to your array:
void Recv(unsigned char *buffer)
{
TRequestStatus iStatus;
TSockXfrLength len;
TBuf8<1000> buff;
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
unsigned char* const tmpbuf = static_cast<char*>(buff.Ptr());
std::copy(tmpbuf, tmpbuf + len, buffer);
}
Notice that the buffer pointer is now passed directly to the function Recv, no further indirection needed since we don't manipulate the pointer directly.
Um, you're trying to delete[] something that's not allocated by you. You're delete[]ing buff.Ptr() while leaking the array allocated in main().