|
I want to swap two string
#include <stdio.h>
#include <string.h>
void swap(char *a1, char *a2)
{
char ch[20];
if (a1 != NULL || a2 != NULL)
{
strcpy(ch, a1);
strcpy(a1, a2);
strcpy(a2, ch);
}
else
return ;
}
int main()
{
char *a1 = "hello";
char *a2 = "world";
printf("Before the swap a1=%s, a2=%s", a1, a2);
swap(a1, a2);
printf("After the swap a1=%s, a2=%s", a1, a2);
return 0;
}
|
|
|
|
|
Remember what I said about the difference between pointers and arrays earlier? What's probably happening is that the arrays your pointers are pointing to are in a chunk of memory in the program's text section. This section is usually read only - you don't want programs modifying their own code as a rule.
The first strcpy will work okay - you're copying data from the text section to an array on the stack, which is read/write. when you do the second strcpy you're copying from the text section to another bit of the text section and BOOM says the operating system.
If you declare a1 and a2 as:
char a1[] = "hello";
char a2[] = "world";
it'll start working if I'm correct.
Another way of looking at it is...
char a[] = "Hello";
translates to:
- allocate enough memory on the stack to hold 6 characters
- copy "Hello\0" into the memory
while:
char *a = "Hello";
translates to:
- allocate enough memory on the stack to hold a pointer
- initialise the pointer with the address of the constant string "Hello" in the text section
Incidentally this being able to use a char * to point at a const block of characters initialised at compile time is a legacy of the original K&R C which didn't have things like const - it's one of the irritating bits of programming in C. Unfortunately you just have to get used to it.
Hope that helps,
Ash
|
|
|
|
|
thanks !
but I still have question why this can be run
#include <iostream.h>
#include <cstring>
void swap(char *,char *);
int main()
{char str1[20]="hello",str2[20]="how are you ";
char pt[20];
cout<<"str1"<<" "<<str1<<endl;
cout<<"str2"<<" "<<str2<<endl;
strcpy(pt,str1);
strcpy(str1,str2);
strcpy(str2,pt);
cout<<"str1"<<" "<<str1<<endl;
cout<<"str2"<<" "<<str2<<endl;
return 0;
}
|
|
|
|
|
That works because you're using arrays - you're saying "allocate 20 bytes on the stack and initialise it with this string." With the original version you were saying "Initialise this pointer to point at a chunk of read only memory."
The difference is where the data your swapping is in memory. Have a look at the address of your variables in a debugger. You'll probably see all three having similar addresses in the second version. In the first version the a1 and a2 will have similar addresses and a lot different to that of the swap temporary.
Cheers,
Ash
|
|
|
|
|
Read here.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Thanks for posting that, the piccies work far better than my text.
Ash
|
|
|
|
|
Use & with the * in swap.
char*& a1
|
|
|
|
|
Your problem seems to be obvious.You are not allowed to modify string contents if they are allocated like a1 and a2.You should probably change your code like that:
char a1[20];
strcpy(a1,"Hello");
char a2[20];
strcpy(a2,"world");
In addition there was almost the same thread recently.
Life is a stage and we are all actors!
|
|
|
|
|
wonderful!
I see, thanks in advance!
|
|
|
|
|
You don't need the explicit strcpy call, the compiler will generate the code to initialise the array properly if you just use:
char a[ 20 ] = "Hello";
Ash
|
|
|
|
|
There is another access violation waiting to happen in your swap function. None of the arguments in a call to strcpy can be null. You need to check for a1 != NULL && a2 != NULL .
Also, watch out for the buffer overruns you might encounter if a1 is longer than 19 characters, or the allocated buffers of a2 and a1 are of different sizes.
|
|
|
|
|
Hi, I tried using Stealing Program's Memory[^][^] in C++. That worked fine for the demo application provided with it, but when I tried to use it with a another application, I was just able to get the total number of Items in the Listview, without the Items details
Could you please help
Thanks
|
|
|
|
|
iceeeeman wrote: Hi, I tried using Stealing Program's Memory[^][^] in C++.
But this link goes to a C# discussion.
iceeeeman wrote: ...without the Items details
Could you please help
Are you using ReadProcessMemory() ? If so, are you checking it's return value (and then using GetLastError() if it fails)?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Hi David, here's the link: Stealing Program's Memory[^]
Yes, using it.
I difference I noticed is that my source application has a AFX window, but I guess that's not a problem since I m able to get the Item Count !!
|
|
|
|
|
of course integers work fine, they are passed as is, even across process boundaries.
However text/string operations such as GetWindowText and GetItemText need memory to read/write the text data; such memory must reside in the address space of the process where the data lives; you can only access that using those special Windows calls e.g. ReadProcessMemory.
The technique is used (in C#) in my LP#TrayIconBuster[^] article; have a look at the LP_Process class there.
|
|
|
|
|
Already using ReadProcessMemory, here's the code (source: Stealing Program's Memory[^])
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
int main(void) {
HWND hwnd=FindWindow(NULL, "Stealing Program's Memory: ListView");
HWND listview=FindWindowEx(hwnd, NULL, "SysListView32", NULL);
int count=(int)SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
int i;
LVITEM lvi, *_lvi;
char item[512], subitem[512];
char *_item, *_subitem;
unsigned long pid;
HANDLE process;
GetWindowThreadProcessId(listview, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
MEM_COMMIT, PAGE_READWRITE);
_item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
_subitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
PAGE_READWRITE);
lvi.cchTextMax=512;
for(i=0; i<count; i++) {
lvi.iSubItem=0;
lvi.pszText=_item;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=1;
lvi.pszText=_subitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _item, item, 512, NULL);
ReadProcessMemory(process, _subitem, subitem, 512, NULL);
printf("%s - %s\n", item, subitem);
}
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _item, 0, MEM_RELEASE);
VirtualFreeEx(process, _subitem, 0, MEM_RELEASE);
return 0;
}
Its working fine for the demo application, I used create a from in VB and used it, it worked there fine too, but not sure what's causing it to show null values for one the application that has AFX window !!
|
|
|
|
|
How do you know that WriteProcessMemory() and ReadProcessMemory() are working?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
could you please let me know the way to chk it out?
Thanks
|
|
|
|
|
read the documentation!
your code is not safe.
(almost) all Win32 functions have a way to report success/failure and/or an error code.
you should use it. ALWAYS.
|
|
|
|
|
In the same way you'd check the return value from any other function.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Hi just checked it, they seem to return 1
|
|
|
|
|
both of them returned 1, I just noticed LVS_OWNERDRAWFIXED for my source application's list-view, any ideas on the modifications required in the code to get the list of Items
|
|
|
|
|
If you think that style is causing a problem, create another control without it and see what happens.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
|
i load an Cimage file in my SDI MFC (non View/Doc arch.) application & draw some shapes & text on it... tell me how i can save both shapes,texts & CImage in any (jpg,bmp) file format...
|
|
|
|
|