i am faced with a problem , i write this code in windows which reads each line of the file. and it works well in windows 7 but not in liunx. i really can't figure it out. anyone can help me?
list< list<string> > getTransRecordsFormFile(const char* fileName)
{
list< list<string> > res;
FILE* f = fopen(fileName,"r");
if(f == NULL) {
cout << "load input file failed!" << endl;
exit(0);
}
else {
char *buffer;
while(fgets(buffer,MAX_LENTH,f) != NULL) {
list<string> v = splitStr(buffer, SPLITCHAR);
res.push_back(v);
}
}
fclose(f);
return res;
}
i and my classmates find it out that the "fgets" in this code is wrong , but i don't know it works well in windows.
In your code, buffer is left unitialized. So, it may very well (and most likely to) points to some invalid memory location. Accessing invalid memory invokes undefined behavior. Once your program hits UB, absolutely nothing is guaranteed.
You need to make buffer point to some valid memory location before you can use that in fgets().
Related
I'm writing my first project trying to use System.Text.Json in a .net core app. I'm getting a jsonl file with a particular structure, and my requirements are in effect to UNPIVOT/flatten an array of child objects in one object into a stream of transformed objects.
It was going fine until I put a breakpoint on the routine doing the UNPIVOT and the debugger itself started blowing up with an access violation in JsonElement.DebuggerDisplay.get. Interestingly,
a) it floats around which row it blows up on and b) it seems to be somewhat dependent on how long I wait before clicking Continue. In other words, if I wait a couple of seconds, it seems to work; if I click right away it blows up faster.
Just wondering if anyone else had run into something like this. And whether I should just switch back to NewtonSoft to avoid the headache.
Here's what my code looks like:
public static IEnumerable<MyResult> ConvertJson(JsonElement input)
{
JsonElement transformArray, base_url;
if (!input.TryGetProperty("child_objects", out transformArray) || transformArray.ValueKind != JsonValueKind.Array)
yield break;
if (!input.TryGetProperty("base_url", out base_url) || base_url.ValueKind != JsonValueKind.String)
yield break;
int i = 0;
foreach(var o in transformArray.EnumerateArray())
{
// Break point on line below. Click Continue too quickly, and I get DebuggerDisplay.get access violation
var result = new MyResult();
result.BaseURL = base_url.ToString();
result.PageID = i; i++;
JsonElement prop;
if (o.TryGetProperty("prop1", out prop) && prop.ValueKind == JsonValueKind.String) result.Prop1 = prop.ToString();
if (o.TryGetProperty("text", out prop) && prop.ValueKind == JsonValueKind.String) result.Text = prop.ToString();
if (o.TryGetProperty("language", out prop) && prop.ValueKind == JsonValueKind.String) result.Language = prop.ToString();
yield return result;
}
}
and it's called like this:
string l = JsonlStream.ReadLine();
var json = JsonSerializer.Deserialize<JsonElement>(l);
foreach (var i in ConvertJson(json))
{
...
}
I'm new to QT and I'm trying to create an encrypted function.
Overall what you do in C / C ++ is:
Take pointer to function
make the function page rwx
Encrypt it (for the example I encrypt and decrypt in the same program)
Decrypt it and run it
A simple code in C will happen roughly like this:
void TestFunction()
{
printf("\nmsgbox test encrypted func\n");
}
// use this as a end label
void FunctionStub() { return; }
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
char * addr = (char *)dwStartAddress;
for (int i = 0; i< dwSize; i++)
{
addr[i] ^= 0xff;
}
}
DWORD GetFuncSize(DWORD* Function, DWORD* StubFunction)
{
DWORD dwFunctionSize = 0, dwOldProtect;
DWORD *fnA = NULL, *fnB = NULL;
fnA = (DWORD *)Function;
fnB = (DWORD *)StubFunction;
dwFunctionSize = (fnB - fnA);
VirtualProtect(fnA, dwFunctionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // make function page read write execute permission
return dwFunctionSize;
}
int main()
{
DWORD dwFuncSize = GetFuncSize((DWORD*)&TestFunction, (DWORD*)&FunctionStub);
printf("use func");
TestFunction();
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR encrypt the function
printf("after enc");
//TestFunction(); // If you try to run the encrypted function you will get Access Violation Exception.
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR decrypt the function
printf("after\n");
TestFunction(); // Fine here
getchar();
}
When I try to run such an example in QT I get a run time error.
Here is the code in QT:
void TestFunction()
{
QMessageBox::information(0, "Test", "msgbox test encrypted func");
}
void FunctionStub() { return; }
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
char * addr = (char *)dwStartAddress;
for (int i = 0; i< dwSize; i++)
{
addr[i] ^= 0xff; // here i get seg. fault
}
}
DWORD GetFuncSize(DWORD* Function, DWORD* StubFunction)
{
DWORD dwFunctionSize = 0, dwOldProtect;
DWORD *fnA = NULL, *fnB = NULL;
fnA = (DWORD *)Function;
fnB = (DWORD *)StubFunction;
dwFunctionSize = (fnB - fnA);
VirtualProtect(fnA, dwFunctionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // Need to modify our privileges to the memory
QMessageBox::information(0, "Test", "change func to read write execute ");
return dwFunctionSize;
}
void check_enc_function()
{
DWORD dwFuncSize = GetFuncSize((DWORD*)&TestFunction, (DWORD*)&FunctionStub);
QMessageBox::information(0, "Test", "use func");
TestFunction();
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR encrypt the function -> ### i get seg fault in here ###
QMessageBox::information(0, "Test", "after enc");
TestFunction(); // If you try to run the encrypted function you will get Access Violation Exception.
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR decrypt the function
QMessageBox::information(0, "Test", "after dec");
TestFunction(); // Fine here
getchar();
}
Why should this happen?
QT is supposed to behave like precision as standard C ++ ...
post Scriptum.
Interestingly in the same matter, what is the most legitimate way to keep an important function encrypted (the reason it is encrypted is DRM)?
Legitimately I mean that anti-viruses will not mistakenly mark me as a virus because I defend myself.
PS2
If I pass an encrypted function over the network (say, I will build a server client schema that the client asks for the function it needs to run from the server and the server sends it to it if it is approved) How can I arrange the symbols so that the function does not collapse?
PS3
How in QT can I turn off the DEP and ASLR defenses? (In my opinion so that I can execute PS 2. I have to cancel them)
Thanks
yoko
The example is undefined behaviour on my system.
The first and main issue in your code is:
void TestFunction() { /* ... */ }
void FunctionStub() { return; }
You assume that the compiler will put FunctionStub after TestFunction without any padding. I compiled your example and FunctionStub in my case was above TestFunction which resulted in a negative dwFunctionSize.
dwFunctionSize = (fnB - fnA);
TestFunction located at # 0xa11d90
FunctionStub located at # 0xa11b50
dwFunctionSize = -0x240
Also in XorBlock
addr[i] ^= 0xff;
Is doing nothing.
I assume you want to write in XorBlock to the memory location to XOR the entire TestFunction.
You could do something like this:
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
DWORD dwEndAddress = dwStartAddress + dwSize;
for(DWORD i = dwStartAddress; i < dwEndAddress; i++) {
// ...
}
}
I can't see any Qt-specific in your example. Even if it's Qt function call it's just a call. So I guess you have undefined behaviour in both examples but only second one crashes.
I can't see any reason for compiler and linker to keep function order. For example GCC let you specify the code section for each function. So you can reorder it in executable without reordering in cpp.
I think you need some compiler specific things to make it work.
I'm trying to create and implement a DDE dll with Qt but as for now I'm being unable to properly connect to a service which I know to be working after testing it with Excel.
The dll connection function is as following:
UINT respTemp;
respTemp = DdeInitializeA(&pidInst, NULL, APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0L);
//handle error messages here
//...
//![]
hszService = DdeCreateStringHandleA(pidInst, (LPCSTR)service.utf16(), CP_WINANSI); //service.toLatin1().toStdString().c_str()
hszTopic = DdeCreateStringHandleA(pidInst, (LPCSTR)topic.utf16(), CP_WINANSI); //topic.toLatin1().toStdString().c_str()
hConv = DdeConnect(pidInst, hszService, hszTopic, NULL);
DdeFreeStringHandle(pidInst, hszService);
DdeFreeStringHandle(pidInst, hszTopic);
if (!hConv)
{
UINT ddeLastError = DdeGetLastError(pidInst);
switch (ddeLastError)
{
case DMLERR_DLL_NOT_INITIALIZED: return DDEConn_DLLNotInitialized;
case DMLERR_INVALIDPARAMETER: return DDEConn_InvalidParameter;
case DMLERR_NO_CONV_ESTABLISHED: return DDEConn_NoConvEstablished;
default: return DDEConn_NoConnectionStablished;
}
}
connStatus = true;
return DDEConn_NoError;
The test function is as follows:
void MainWindow::on_start_clicked()
{
const QString application = "profitchart"; //=profitchart|COT!VALE5.ult
const QString topic = "COT";
const QString item = "VALE5.ult";
test = CommDDE::instance();
CommDDE::DDEConnectionErrorList resp = test->connect(application,topic);
if (resp == CommDDE::DDEConn_NoError)
{
qDebug() << "request RESULT: " << test->request(item);
}
else
qDebug() << "Can't connect to application" << resp;
}
Always when I try to connect I get error DMLERR_NO_CONV_ESTABLISHED after the call to DdeConnect. I couldn't find guidence on what to do when such error occurs. I don't know too much about the details of configuring such functions so I used the default configuration used by a working dll from which I got part of the raw material for this dll. Should I try a different configuration I'm not aware of? Remembering that the call is working on Excel.
It would seem I found the answer: the commented way of writting the service and topic names were the right ways of passing the parameters to DdeCreateStringHandleA and DdeCreateStringHandleA.
I'm trying to take an nginx buffer chain and work with it in some experimental code. In order to do so, I need to first flatten the chain into a single block of memory. Here's what I've got so far (actual production code is a bit different, so this is untested):
u_char *flatten_chain(ngx_chain_t *out) {
off_t bsize;
ngx_chain_t *out_ptr;
u_char *ret, *ret_ptr;
uint64_t flattenSize = 0;
out_ptr = out;
while (out_ptr) {
if(!out_ptr->buf->in_file) {
bsize = ngx_buf_size(out_ptr->buf);
flattenSize += bsize;
}
out_ptr = out_ptr->next;
}
ret = malloc(flattenSize);
ret_ptr = ret;
out_ptr = out;
while (out_ptr) {
bsize = ngx_buf_size(out_ptr->buf);
if(!out_ptr->buf->in_file) {
memcpy(ret_ptr, out_ptr->buf->pos, (size_t)bsize);
ret_ptr += bsize;
}
out_ptr = out_ptr->next;
}
return(ret);
}
However, it doesn't seem to work. Disclaimer: it's possible that it does work and my data is getting corrupted somewhere else... but while I look into that, can someone please confirm or deny that the above should work?
Thanks!
I wrote a program to test my binary tree and when I run it, the program seems to crash (btree.exe has stopped working, Windows is checking for a solution ...).
When I ran it through my debugger and placed the breakpoint on the function I suspect is causing it, destroy_tree(), it seemed to run as expected and returned back to the main function. Main, in turn, returned from the program but then the cursor jumped back to destroy_tree() and looped recusively within itself.
The minimal code sample is below so it can be ran instantly. My compiler is MinGW and my debugger is gdb (I'm using Code::Blocks).
#include <iostream>
using namespace std;
struct node
{
int key_value;
node *left;
node *right;
};
class Btree
{
public:
Btree();
~Btree();
void insert(int key);
void destroy_tree();
private:
node *root;
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
};
Btree::Btree()
{
root = NULL;
}
Btree::~Btree()
{
destroy_tree();
}
void Btree::destroy_tree()
{
destroy_tree(root);
cout<<"tree destroyed\n"<<endl;
}
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void Btree::insert(int key, node *leaf)
{
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left = new node;
leaf->left->key_value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if (key >= leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right = new node;
leaf->right->key_value = key;
leaf->right->left = NULL;
leaf->right->right = NULL;
}
}
}
void Btree::insert(int key)
{
if(root!=NULL)
{
insert(key, root);
}
else
{
root = new node;
root->key_value = key;
root->left = NULL;
root->right = NULL;
}
}
int main()
{
Btree tree;
int i;
tree.insert(1);
tree.destroy_tree();
return 0;
}
As an aside, I'm planning to switch from Code::Blocks built-in debugger to DDD for debugging these problems. I heard DDD can display visually pointers to objects instead of just displaying the pointer's address. Do you think making the switch will help with solving these types of problems (data structure and algorithm problems)?
Your destroy_tree() is called twice, you call it once and then it gets called after the execution leaves main() from the destructor.
You may think it should work anyway, because you check whether leaf!=NULL, but delete does not set the pointer to NULL. So your root is not NULL when destroy_tree() is called for the second time,
Not directly related (or maybe it is) to your problem, but it's good practice to give structs a constructor. For example:
struct node
{
int key_value;
node *left;
node *right;
node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
If you do this, your code becomes simpler, because you don't need worry about setting the pointers when you create a node, and it is not possible to forget to initialise them.
Regarding DDD, it;'s a fine debugger, but frankly the secret of debugging is to write correct code in the first place, so you don't have to do it. C++ gives you a lot of help in this direction (like the use of constructors), but you have to understand and use the facilities it provides.
Btree::destroy_tree doesn't set 'root' to 0 after successfully nuking the tree. As a result, the destructor class destroy_tree() again and you're trying to destroy already destroyed objects.
That'll be undefined behaviour then :).
Once you destroy the root.
Make sure it is NULL so it does not try to do it again (from the destructor)
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
leaf = NULL; // add this line
}
}