I wanted to show a memory address in a QLabel. When I compile the following code, it give me error:
// Allocate space for our DLL path inside the target remote process.
LPVOID dll_path_in_remote_mem_addr = VirtualAllocEx(
target_process,
NULL,
_MAX_PATH,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if (dll_path_in_remote_mem_addr == NULL) {
QMessageBox::warning(this, "Failed OPS", "Allocating space for our DLL path in the remote target process's virtual memory space failed...");
CloseHandle(target_process);
}
else
{
ui->labelDllAllocationAddress->setText(&dll_path_in_remote_mem_addr);
}
After compilation process, it shows me the following error:
error: C2664: 'void QLabel::setText(const QString &)': cannot convert argument 1 from 'LPVOID *' to 'const QString &'
How can I show a memory address of LPVOID type in widget like QLabel?
First you need to convert your address to a QString type. As it is an address, you probably want to see it in its hexadecimal form :
EDIT : as the LPVOID value is not implicitly cast to an int, you need to do it yourself.
EDIT2 : the long type is not big enough to hold the pointer (64-bit machine), so you need to use long long.
unsigned long address = reinterpret_cast<long long>(dll_path_);
QString addressInTextValue = QString("%1").arg(address, 0, 16);
This is documented here : https://doc.qt.io/qt-5/qstring.html
Related
I have began learning C++ for Arduino and have run into some troubles.
I have some functions reading/writing to SPIFFS files.
Since the code for opening configuration files is common I would want to have a separate function to handle it.
I have come up with following function declaration
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file);
The function accepts pointer to char array for the file path, and pointer to opened file.
I then tried to make following function definition
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file)
{
if (SPIFFS.exists(path))
{
file = &SPIFFS.open(path, "r+");
return !file ? Failed : Opened;
}
else
{
file = &SPIFFS.open(path, "w+");
return !file ? Failed : Created;
}
}
That did not work as compiler complained with error error: taking address of temporary [-fpermissive]
As I understand this means that the file object will be disposed once DeviceOpenConfigFile function returns?
So my question is whether its possible to implement a function in a way where I can get File object reference and release it later?
SPIFFS.open apparently returns File, by value. The returned value will be a temporary variable available on that line. So taking the address of that one doesn't make any sense, for the same reason as int func (void); ... &func() doesn't make any sense. It has nothing to do with the surrounding DeviceOpenConfigFile function.
It doesn't make sense to assign a new address to pointer passed by parameter, for the same reason as void func (int x) { x = 0; } doesn't make sense - you change a local variable only, nothing on the caller side gets changed and nothing gets returned to the caller.
It would seem that the solution you are looking for is this:
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File* file)
{
...
*file = SPIFFS.open(path, "r+");
where file is allocated on the caller-side.
I was trying to understand underlying process when pointers, strings and functions are combined along with heap/stack memory. I was able to understand and learn, but I ended up with two errors which I failed to find out why.
My problem lies here:
// printf("%s\n", *ptrToString); // Gives bad mem access error if heap memory used
// printf("%s\n", ptrToString); // Output is wrong if stack was used for memory, and prints some hex values instead
Can anyone explain what am I missing here ? Also, I would like to ask some feedback about my code, and suggest any improvements we can make.
Thanks
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define USE_STACK_MEMORY 0
char* NewString(char string[])
{
unsigned long num_chars;
char *copy = NULL;
// Find string length
num_chars = strlen(string);
// Allocate memory
#if USE_STACK_MEMORY
copy = alloca(sizeof(copy) + num_chars + 1); // Use stack memory
#else
copy = malloc(sizeof(copy) + num_chars + 1); // Use heap memory
#endif
// Make a local copy
strcpy(copy, string);
// If we use stack then it returns a string literal
return copy;
}
int main(void)
{
char *ptrToString = NULL;
ptrToString = NewString("HI");
printf("%s\n", ptrToString);
// printf("%s\n", *ptrToString); // Gives bad mem access error if heap memory used
// printf("%s\n", ptrToString); // Output is wrong if stack was used for memory, and prints some hex values instead
#if !USE_STACK_MEMORY
if ( ptrToString ) {
free(ptrToString);
}
#endif
return 0;
}
The first print reads the value where the pointer points to. It interprets this value then as a pointer to a string. This means the first value of your string will be interpreted as the address where the string would be.
The second print is wrong for stack memory because the memory you allocate with alloca is automatically freed as soon as your NewString method returns.
From the man page of alloca:
The alloca() function allocates size bytes of space in the stack frame
of the caller. This temporary space is automatically freed when the
function that called alloca() returns to its caller.
I am trying to get networking information (IP Address, Netmask, Route etc.) for all my interfaces in Qt using NetworkManager DBus interface. The problem is when I try to access the property "Addresses" of org.freedesktop.NetworkManager.IP4Config I get the following error
QDBusAbstractInterface: type QDBusRawType<0x616175>* must be registered with QtDBus before it can be used to read property org.freedesktop.NetworkManager.IP4Config.Addresses
Addresses are invalid
Error 2 = "Unregistered type QDBusRawType<0x616175>* cannot be handled"
However I can get the value of this property using dbus-send with following command.
dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/IP4Config/0 \
org.freedesktop.DBus.Properties.Get \
string:"org.freedesktop.NetworkManager.IP4Config" \
string:"Addresses"
I can also get good values for above interface's mentioned property via qtdbusviewer. Following is my code snippet.
QDBusInterface interface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_IFACE, QDBusConnection::systemBus());
// Get a list of all devices
QDBusReply<QList<QDBusObjectPath> > result = interface.call("GetDevices");
foreach (const QDBusObjectPath& connection, result.value()) {
QDBusInterface device(NM_DBUS_SERVICE, connection.path(), "org.freedesktop.NetworkManager.Device", QDBusConnection::systemBus());
if ( device.property("DeviceType").toInt() == NM_DEVICE_TYPE_ETHERNET ) {
// Get the IPv4 information if the device is active
if ( device.property("State").toInt() == NETWORK_DEVICE_CONNECTED ) {
QVariant ipv4config = device.property("Ip4Config");
if ( ipv4config.isValid() ) {
QDBusObjectPath path = qvariant_cast<QDBusObjectPath>(ipv4config);
QDBusInterface ifc(NM_DBUS_SERVICE, path.path(), "org.freedesktop.NetworkManager.IP4Config", QDBusConnection::systemBus());
if ( ifc.isValid() ) {
qDebug() << "Error 1 = " << ifc.lastError().message(); // No error. Everything is OK.
QVariant addresses = ifc.property("Addresses"); // Throwing the QDBusAbstractInterface Error where the property is good and does exist.
if ( addresses.isValid() ) {
qDebug () << "Addresses are valid";
} else {
qDebug () << "Addresses are invalid";
}
qDebug() << "Error 2 = " << ifc.lastError().message();
}
}
}
}
}
UPDATE # 1
I think it appears to be problem of types. Qt-Dbus type system does not understand the type of "Addresses" property so unable to create a QVariant out of it. So I added following lines before reading the property "Addresses". NetworkManager defines the property Addresses as following type, so I guess my typedef is good.
aau - "Array of tuples of IPv4 address/prefix/gateway. All 3 elements of each tuple are in network byte order. Essentially: [(addr, prefix, gateway), (addr, prefix, gateway), ...]"
typedef QList<QList<uint> > Addresses;
Q_DECLARE_METATYPE(Addresses)
qDBusRegisterMetaType<Addresses>()
QVariant addresses = ifc.property("Addresses");
Also I switched to Qt 5.1 (Earlier I was using 4.8), and I am getting the same error in following form.
Cannot construct placeholder type QDBusRawType
Thoughts / Suggestions
Regards,
Farrukh Arshad.
So far as per my research the problem is related to the type conversion. The property value is in the form of aau (as per NM Dbus documentation). QDbusInterface.property returns QVariant. It does find the property but unable to determine the type of the property hence giving me the error message. But my concern is, I have registered the custom type of this property with the Qt Meta Object system as I have mentioned in the Update # 1 then why it is giving me this error my type was registered with the system properly and qDBusRegisterMetaType did returned me a valid integer. In Qt 5.1 the origin of the error is in qdbusmaster.cpp. One article suggests to register meta type as mentioned below, but to no avail.
qRegisterMetaType<Addresses>("Addresses");
qDBusRegisterMetaType<Addresses>();
For now I don't have time to further dig into to see if it is some bug or I am missing something, but I will update this post once I have actual solution.
WORKAROUND
Following workaround will work to read the given property value. For this workaround to work you need to add qdbus-private instead of qdbus and include .
QVariant ipv4config = device.property("Ip4Config");
if ( ipv4config.isValid() ) {
QDBusObjectPath path = qvariant_cast<QDBusObjectPath>(ipv4config);
QDBusMessage message = QDBusMessage::createMethodCall(NM_DBUS_SERVICE, path.path(), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get"));
QList<QVariant> arguments;
arguments << "org.freedesktop.NetworkManager.IP4Config" << "Addresses";
message.setArguments(arguments);
QDBusConnection connection = QDBusConnection::systemBus();
QDBusMessage reply = connection.call(message);
foreach(QVariant var, reply.arguments()) {
qDebug () << "String = " << QDBusUtil::argumentToString(var).toHtmlEscaped();
}
}
The string will show you the IP Address / Subnet Mask / Router IP which you will have to extract from the output. For record, I have taken this approach from qdbusviewer.
This is not the the right solution, but it will get you out of trouble for the time being. There is also a good article suggesting usage of custom types with Qt Dbus.
http://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes
The best solution I've found for this has been to write a QDBusAbstractInterface implementation:
typedef QList<QList<uint> > UIntListList;
Q_DECLARE_METATYPE(UIntListList)
class DBusIP4ConfigInterface : public QDBusAbstractInterface
{
Q_OBJECT
public:
DBusIP4ConfigInterface(const QString &service, const QString &path, const QDBusConnection &connection,
QObject *parent = 0)
{
qDBusRegisterMetaType<UIntListList>();
}
virtual ~DBusIP4ConfigInterface() { }
Q_PROPERTY(UIntListList Addresses READ addresses)
UIntListList addresses() const
{
return qvariant_cast<UIntListList>(property("Addresses"));
}
Q_PROPERTY(QString Gateway READ gateway)
QString gateway() const
{
return qvariant_cast<QString>(property("Gateway"));
}
Q_SIGNALS:
void PropertiesChanged(const QVariantMap &properties);
};
This has the added advantage of being pretty easy to use:
UIntListList addresses = m_dbusIP4Config->addresses();
Q_ASSERT(addresses.size() >= 1);
Q_ASSERT(addresses[0].size() == 3);
QHostAddress ip = QHostAddress(qFromBigEndian(addresses[0][0]));
So I've been stuck on a memory problem for days now.
I have a multi-threaded program running with c++. I initialize a double* pointer.
From what I've read and previous programming experience, a pointer gets initialized to garbage. It will be Null if you initialize it to 0 or if you allocate memory that's too much for the program. For me, my pointer initialization, without allocation, gives me a null pointer.
A parser function I wrote is suppose to return a pointer to the array of parsed information. When I call the function,
double* data;
data = Parser.ReadCoordinates(&storageFilename[0]);
Now the returned pointer to the array should be set to data. Then I try to print something out from the array. I get memory corruption errors. I've ran gdb and it gives me a memory corruption error:
*** glibc detected *** /home/user/kinect/openni/Platform/Linux/Bin/x64-Debug/Sample-NiHandTracker: free(): corrupted unsorted chunks: 0x0000000001387f90 ***
*** glibc detected *** /home/user/kinect/openni/Platform/Linux/Bin/x64-Debug/Sample-NiHandTracker: malloc(): memory corruption: 0x0000000001392670 ***
Can someone explain to me what is going on? I've tried initializing the pointer as a global but that doesn't work either. I've tried to allocate memory but I still get a memory corruption error. The parser works. I've tested it out with a simple program. So I don't understand why it won't work in my other program. What am I doing wrong? I can also provide more info if needed.
Parser code
double* csvParser::ReadCoordinates(char* filename){
int x; //counter
int size=0; //
char* data;
int i = 0; //counter
FILE *fp=fopen(filename, "r");
if (fp == NULL){
perror ("Error opening file");
}
while (( x = fgetc(fp)) != EOF ) { //Returns the character currently pointed by the internal file position indicator
size++; //Number of characters in the csv file
}
rewind(fp); //Sets the position indicator to the beginning of the file
printf("size is %d.\n", size); //print
data = new char[23]; //Each line is 23 bytes (characters) long
size = (size/23) * 2; //number of x, y coordinates
coord = new double[size]; //allocate memory for an array of coordinates, need to be freed somewhere
num_coord = size; //num_coord is public
//fgets (data, size, fp);
//printf("data is %c.\n", *data);
for(x=0; x<size; x++){
fgets (data, size, fp);
coord[i] = atof(&data[0]); //convert string to double
coord[i+1] = atof(&data[11]); //convert string to double
i = i+2;
}
delete[] data;
fclose (fp);
return coord;
}
Corrupt memory occurs when you write outside the bound of an array or vector.
It's called heap underrun and overrun (depends on which side it's on).
The heap's allocation data gets corrupted, so the symptom you see is an exception in free() or new() calls.
You usually don't get an access violation because the memory is allocated and it belongs to you, but it's used by the heap's logic.
Find the place where you might be writing outside the bounds of an array.
have C sources that must compile in 32bit and 64bit for multiple platforms.
structure that takes the address of a buffer - need to fit address in a 32bit value.
obviously where possible these structures will use natural sized void * or char * pointers.
however for some parts an api specifies the size of these pointers as 32bit.
on x86_64 linux with -m64 -mcmodel=small tboth static data and malloc()'d data fit within the 2Gb range. data on the stack, however, still starts in high memory.
so given a small utility _to_32() such as:
int _to_32( long l ) {
int i = l & 0xffffffff;
assert( i == l );
return i;
}
then:
char *cp = malloc( 100 );
int a = _to_32( cp );
will work reliably, as would:
static char buff[ 100 ];
int a = _to_32( buff );
but:
char buff[ 100 ];
int a = _to_32( buff );
will fail the assert().
anyone have a solution for this without writing custom linker scripts?
or any ideas how to arrange the linker section for stack data, would appear it is being put in this section in the linker script:
.lbss :
{
*(.dynlbss)
*(.lbss .lbss.* .gnu.linkonce.lb.*)
*(LARGE_COMMON)
}
thanks!
The stack location is most likely specified by the operating system and has nothing to do with the linker.
I can't imagine why you are trying to force a pointer on a 64 bit machine into 32 bits. The memory layout of structures is mainly important when you are sharing the data with something which may run on another architecture and saving to a file or sending across a network, but there are almost no valid reasons that you would send a pointer from one computer to another. Debugging is the only valid reason that comes to mind.
Even storing a pointer to be used later by another run of your program on the same machine would almost certainly be wrong since where your program is loaded can differ. Making any use of such a pointer would be undefined abd unpredictable.
the short answer appears to be there is no easy answer. at least no easy way to reassign range/location of the stack pointer.
the loader 'ld-linux.so' at a very early stage in process activation gets the address in the hurd loader - in the glibc sources, elf/ and sysdeps/x86_64/ search out elf_machine_load_address() and elf_machine_runtime_setup().
this happens in the preamble of calling your _start() entry and related setup to call your main(), is not for the faint hearted, even i couldn't convince myself this was a safe route.
as it happens - the resolution presents itself in some other old school tricks... pointer deflations/inflation...
with -mcmodel=small then automatic variables, alloca() addresses, and things like argv[], and envp are assigned from high memory from where the stack will grow down. those addresses are verified in this example code:
#include <stdlib.h>
#include <stdio.h>
#include <alloca.h>
extern char etext, edata, end;
char global_buffer[128];
int main( int argc, const char *argv[], const char *envp )
{
char stack_buffer[128];
static char static_buffer[128];
char *cp = malloc( 128 );
char *ap = alloca( 128 );
char *xp = "STRING CONSTANT";
printf("argv[0] %p\n",argv[0]);
printf("envp %p\n",envp);
printf("stack %p\n",stack_buffer);
printf("global %p\n",global_buffer);
printf("static %p\n",static_buffer);
printf("malloc %p\n",cp);
printf("alloca %p\n",ap);
printf("const %p\n",xp);
printf("printf %p\n",printf);
printf("First address past:\n");
printf(" program text (etext) %p\n", &etext);
printf(" initialized data (edata) %p\n", &edata);
printf(" uninitialized data (end) %p\n", &end);
}
produces this output:
argv[0] 0x7fff1e5e7d99
envp 0x7fff1e5e6c18
stack 0x7fff1e5e6a80
global 0x6010e0
static 0x601060
malloc 0x602010
alloca 0x7fff1e5e69d0
const 0x400850
printf 0x4004b0
First address past:
program text (etext) 0x400846
initialized data (edata) 0x601030
uninitialized data (end) 0x601160
all access to/from the 32bit parts of structures must be wrapped with inflate() and deflate() routines, e.g.:
void *inflate( unsigned long );
unsigned int deflate( void *);
deflate() tests for bits set in the range 0x7fff00000000 and marks the pointer so that inflate() will recognize how to reconstitute the actual pointer.
hope that helps if anyone similarly must support structures with 32bit storage for 64bit pointers.