Reading a cubin structure from a pointer - c++

I am trying to read the contents a c++ structure(in windows) which has the following format
typedef struct __cudaFatCudaBinaryRec {
unsigned long magic;
unsigned long version;
unsigned long gpuInfoVersion;
char* key;
char* ident;
char* usageMode;
__cudaFatPtxEntry *ptx;
__cudaFatCubinEntry *cubin;
__cudaFatDebugEntry *debug;
void* debugInfo;
unsigned int flags;
__cudaFatSymbol *exported;
__cudaFatSymbol *imported;
struct __cudaFatCudaBinaryRec *dependends;
unsigned int characteristic;
__cudaFatElfEntry *elf;
} __cudaFatCudaBinary;
I have a pointer to this structure (void *ptr)
Now I am looking to read the contents of this structure.
__cudaFatCudaBinary *ptr2=(cudaFatCudaBinary*)ptr;
cout<<ptr->magic;//This works fine
cout<<ptr->key;//This crashes my program..bad pointer results..why?
The above is consistent with all non pointer and pointer members. What am I doing wrong?
ADDED:
ok let me elaborate on the problem. Yes, the address pointed to by "key" is NULL and so it is for all the pointer members. But I know for sure the structure has valid data. It is used by a driver function to generate a handle and it executes fine. All I need is to copy the entire image of the structure and store it in a text file. How would I do it? Why are some of the member fields null? I am thinking of a brute force way to find the address limits of the structure. But the values themselves seem to be invalid when read and I don't know how to go about it!
ADDED 2
Memory Dump of the structure
Thanks !

cout << ptr->key will print as a 0-terminated string whatever key points to, not the pointer itself. If key is NULL or otherwise invalid then this will be undefined behaviour. (In this case a "crash")
If you just want to print the pointer itself make sure you print it as a void* pointer:
cout << static_cast<void*>(ptr->key);

As of CUDA 4.0, the format of this struct drastically changed. The value of magic is now different and gpuInfoVersion is now a pointer to a struct that contains the actual data. For more information, you might want to read this thread.

Related

cast to pointer from integer of different size when converting uint64_t to bytes

[EDIT]I wanted write uint64_t to char* array in network byte order to send it as UDP datagram with sendto, uint64_t has 8 bytes so I convert them as follow:
void strcat_number(uint64_t v, char* datagram) {
uint64_t net_order = htobe64(v);
for (uint8_t i=0; i<8 ;++i) {
strcat(datagram, (const char*)((uint8_t*)&net_order)[i]);
}
}
wchich give me
warning: cast to pointer from integer of different size [-Wint-to-pointer-xast]
strcat(datagram, (const char*)((uint8_t*)&net_order)[i]);
how can I get rid of this warning or maybe do this number converting simpler or clearer?
((uint8_t*)&net_order)
this is a pointer to net_order casted to a uint8_t pointer
((uint8_t*)&net_order)[i]
this is the i-th byte of the underlying representation of net_order.
(const char*)((uint8_t*)&net_order)[i]
this is the same as above, but brutally casted to a const char *. This is an invalid pointer, and it is what the compiler is warning you about; even just creating this pointer is undefined behavior, and using it in any way will almost surely result in a crash.
Notice that, even if you somehow managed to make this kludge work, strcat is still the wrong function, as it deals with NUL-terminated strings, while here you are trying to put binary data inside your buffer, and binary data can naturally contain embedded NULs. strcat will append at the first NUL (and stop at the first NUL in the second parameter) instead of at the "real" end.
If you are building a buffer of binary data you have to use straight memcpy, and most importantly you cannot use string-related functions that rely on the final NUL to know where the string ends, but you have to keep track explicitly of how many bytes you used (i.e. the current position in the datagram).

Copy multiple void* into one vector

I am coming back to C++ after many years (and never went so deeply before), so please indulge with me for my noobness :)
I have, as a field of a struct, a *void which points to some data. The memory pointed by the struct is filled with different data after every call of a given function, so I'd like to "cache" the results after every function call in a vector, in order to obtain all data in the end. How can I achieve this goal?
I declared a static vector<unsigned char> vectorBuffer; and tried vectorBuffer.insert(vectorBuffer.end(), (unsigned char*)myStruct->thePointer) and vectorBuffer.push_back((unsigned char*)myStruct->thePointer) but obviously I'm getting errors. Which is the correct way to obtain such a result?
Thanks
EDIT: I know the size of the void* as well, since I have another field in my struct that refreshes as the data do.
Something along these lines is what you want to do to buffer the data fragmented over multiple callbacks:
#include <vector>
std::vector<char> buffer;
buffer.insert(buffer.end(), data, data+length);
Assuming that data is your data coming in the callback and length is available too.
You should declare the vector with
static vector<unsigned char *> vectorBuffer;
(it's an array of unsigned character pointers, not unsigned characters).
To save the data (assuming you know the size),
unsigned char *p = new unsigned char[myStruct->bufferLength];
memcpy((void *) p, myStruct->thePointer, myStruct->bufferLength);
vectorBuffer.push_back(p);
You can then keep track of the length with
static vector<unsigned char *> bufferLength;
bufferLength.push_back(myStruct->bufferLength);
Note that you will need to free the memory afterwards.

How is std::string::size() implemented?

cout << sizeof(std::string) << endl;
The result is 8 on my 64-bit machine, which is the same as sizeof(char*), so I am assuming the string class stores only the char*. How, then, is the size function implemented? Is it using strlen (since it is not storing the actual size or the pointer to the ending byte)?
On this page, it shows the size function has a constant time-complexity, so I am confused. And on another page someone has a larger string size.
I am using GCC 4.7.1 on Fedora 64 bit.
There could be many explanations for that. Just because std::string happens to store a pointer and nothing else does not mean that this is necessarily char * pointer to the controlled sequence. Why did you jump to that conclusion?
It could easily turn out that your std::string is a PImpl-style wrapper for a pointer to some internal object that stores all internal household data, including the char * pointer, the length and whatever else is necessary. That way the internal object can be arbitrarily large, without having any effect on the size of std::string itself. For example, in order to facilitate fast reference-counted copying, in some implementations std::string might be implemented similarly to std::shared_ptr. I.e. std::string in that case would essentially become something like std::shared_ptr<std::string_impl> with added copy-on-write semantics.
The target "string implementation" object might even use "struct hack"-style approach to store the actual string, meaning that instead of storing char * pointer it might embed the entire string into itself at the end.
Looking at the doxygen docs for libstdc++:
_CharT* _M_p; // The actual data
Assuming std::basic_string<char>, _M_p is a char* pointer to the actual data, so that is why you are getting 8.
It even says:
Where the _M_p points to the first character in the string, and you
cast it to a pointer-to-_Rep and subtract 1 to get a pointer to the
header.
So, it hides a pointer to the actual representation (capacity, length, etc.) in a block of memory right before where the string data is stored.
Then, there is the following member function to get to the representation:
Rep* _M_rep() const
{ return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
and then they call it like this _M_rep()->_M_length; to get the size for example.
Your assumption that std::string is char* is wrong. Here is one of q few possible implementations with sizeof(std::string)==sizeof(char*):
struct std::string
{
string_implementation
{
size_t size;
size_t buffer_size;
char_traits whatever;
char *buffer; // Here is your actual string!
};
string_implementation *ptr;
}
std::string is a typdef for std::basic_string<char>, and basic_string is defined (on my machine) in file /usr/include/c++/4.4/bits/basic_string.h. There's a lot of indirection in that file, but roughly speeking std::string stores a pointer to actual data
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(_CharT* __dat, const _Alloc& __a)
: _Alloc(__a), _M_p(__dat) { }
_CharT* _M_p; // The actual data.
};
and this is why you observed such behavior. This pointer might might be casted to obtain pointer to structure that describes the well-known string properties (located just in front of actual data):
struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
};
_Rep* _M_rep() const
{ return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }

Interpret strings as packed binary data in C++

I have question about interpreting strings as packed binary data in C++. In python, I can use struct module. Is there a module or a way in C++ to interpret strings as packed binary data without embedding Python?
As already mentioned, it is better to consider this an array of bytes (chars, or unsigned chars), possibly held in a std::vector, rather than a string. A string is null terminated, so what happens if a byte of the binary data had the value zero?
You can either cast a pointer within the array to a pointer to your struct, or copy the data over a struct:
#include <memory>
#pragma pack ( push )
#pragma pack( 1 );
struct myData
{
int data1;
int data2;
// and whatever
};
#pragma pack ( pop )
char* dataStream = GetTheStreamSomehow();
//cast the whole array
myData* ptr = reinterpret_cast<myData*>( dataStream );
//cast from a known position within the array
myData* ptr2 = reinterpret_cast<myData*>( &(dataStream[index]) );
//copy the array into a struct
myData data;
memcpy( &data, dataStream, sizeof(myData) );
If you were to have the data stream in a vector, the [] operator would still work. The pragma pack declarations ensure the struct is single byte aligned - researching this is left as an exercise for the reader. :-)
Basically, you don't need to interpret anything. In C++, strings are
packed binary data; you can interpret them as text, but you're not
required to. Just be aware that the underlying type of a string, in
C++, is char, which can be either signed (range [-128,127] on all
machines I've heard of) or unsigned (usually [0,255], but I'm aware of
machines where it is [0,511]).
To pass the raw data in a string to a C program, use
std::string::data() and std::string::size(). Otherwise, you can
access it using iterators or indexation much as you would with
std::vector<char> (which may express the intent better).
A string in C++ has a method called c_str ( http://www.cplusplus.com/reference/string/string/c_str/ ).
c_str returns the relevant binary data in a string in form of an array of characters. You can cast these chars to anything you wish and read them as an array of numbers.
Eventhough it might be closer to pickling in python, boost serialization may be closest to what you want to achieve.
Otherwise you might want to do it by hand. It is not that hard to make reader/writer classes to convert primitives/classes to packed binary format. I would do it by shifting bytes to avoid host endianess issues.

C++ Struct pointer question

This is probably simple, but im trying to try and understand pointers better.
Lets say I have a struct
struct Person{
char Name[20];
char ID[15];
char Address[50];
char Number[15];
};
and lets say I have a bunch of these stored in memory like one after the other.
so now i declare a new pointer to the struct.
struct Person *ptr;
Will this Pointer start at the FIRST entry? (aka the first "Name") and when I iterate it (aka ptr++) will it go to the next STRUCT or the next "entry" aka like name-->ID--->Address
So lets say Im on the first entry for example and the data is:
Jason Adams
111222333
111 Fake Drive
55555551000
and the second entry is
Matt Johns
111555333
555 Derp lane
1000022434
now I iterate the ptr (ptr++) will the ptr point to second struct (the one with matt johns) or will it point to Jason Adams "ID"
I hope this makes sense?
It will point to the second struct. The pointer will be advanced by sizeof(Person).
As John mentioned, it will be advanced by the size of itself - aka sizeof(Person).
Pointer manipulation is fun however, and you can do things like cast the pointer to a different type. Once you do that, pointer arithmetic will advance by the underlying size of the type. Commonly you'll see pointers casted to (byte *) or (unsigned char *) to allow individual byte access to the underlying data.
First of all, you must allocate memory for your pointer ptr before using it.
auto_ptr<Person> ptr(new Person); //auto_ptr for automatic freeing
After that, you can try below code.
strcpy(ptr->ID, "100"); //For illustraction
int offset = ptr->ID - ptr->Name; //Get offset of ID member
char *pID = ((char *)ptr.get())+ offset;
//Typecast to char pointer and increment by offset to get to ID field
cout<<pID; //Now pId can be used to access ID.
You asked how to access ID attribute by incrementing ptr.
As shown above, you can access ID member of structure.