C# 文本); WriteLine(“获取地址:{0}”,exampleStringPtr.ToInt32()); var lockedPtr=WinAPI.GlobalLock(例如stringptr); var s=Marshal.PtrToStringUni(lockedPtr); GlobalUnlock(lockedPtr); WriteLine(“获取的字符串:{0}”,s); WinAPI.CloseClipboard(); }
我运行程序,暂停它,并通过WinDbg分析内存。然后我制作结果截图并提供给你。因此,我的测试和截图显示: 1.)内存中有一个源对象的多个副本 2.)如果在关闭剪贴板之前更改给定给SetClipboardData调用的源内存,则在再次打开剪贴板之后,剪贴板甚至在源地址上恢复源对象 不是吗?有人能解释一下这些条款是真是假吗 更新2:好的。。我正在重写C++的第三次测试。在这里:C# 文本); WriteLine(“获取地址:{0}”,exampleStringPtr.ToInt32()); var lockedPtr=WinAPI.GlobalLock(例如stringptr); var s=Marshal.PtrToStringUni(lockedPtr); GlobalUnlock(lockedPtr); WriteLine(“获取的字符串:{0}”,s); WinAPI.CloseClipboard(); },c#,string,winapi,clipboard,C#,String,Winapi,Clipboard,我运行程序,暂停它,并通过WinDbg分析内存。然后我制作结果截图并提供给你。因此,我的测试和截图显示: 1.)内存中有一个源对象的多个副本 2.)如果在关闭剪贴板之前更改给定给SetClipboardData调用的源内存,则在再次打开剪贴板之后,剪贴板甚至在源地址上恢复源对象 不是吗?有人能解释一下这些条款是真是假吗 更新2:好的。。我正在重写C++的第三次测试。在这里: #include "stdafx.h" #include "windows.h" #include "conio.h"
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
int main()
{
HWND owner = GetConsoleWindow();
//1.) Copying string to clipboard
if (OpenClipboard(owner))
{
EmptyClipboard();
//WCHAR *str = L"Loooong string example";
char *str = "Loooooooong string Example";
int cch = strlen(str);
char* strptr = (char*)GlobalAlloc(GMEM_MOVEABLE, (cch + 1));
printf("setting (segment??) address: %X \n", strptr);
LPVOID lockedPtr = GlobalLock(strptr);
printf("locked setting address: %X \n", lockedPtr);
// copy
memcpy(lockedPtr, str, cch);
GlobalUnlock(strptr);
// set to clipboard
SetClipboardData(CF_TEXT, strptr);
//2.) Change string while clipboard isn't closed - replace first 10 characters on one any symbol
lockedPtr = GlobalLock(strptr);
for (int i = 0; i < 10; i++)
{
((char*)lockedPtr)[i] = 50;
}
GlobalUnlock(strptr);
//3.) Obtain string and make sure that string was changed
lockedPtr = GlobalLock(strptr);
printf("changed string: %s \n", lockedPtr);
GlobalUnlock(strptr);
//4.) Get this string from clipboard and make sure that clipboard was changed
strptr = (char*)GetClipboardData(CF_TEXT);
printf("getting address: %X \n", strptr);
lockedPtr = GlobalLock(strptr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", (char*)lockedPtr );
GlobalUnlock(strptr);
CloseClipboard();
}
printf("\n-------Close and open clipboard------------------\n");
//5.) Getting string from clipboard
for (int i = 0; i < 10; i++)
{
//Sleep(1000);
if (OpenClipboard(owner))
{
HANDLE exampleStringPtr = GetClipboardData(CF_TEXT);
printf("getting address: %X \n", exampleStringPtr);
char* lockedPtr = (char*)GlobalLock(exampleStringPtr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", lockedPtr);
GlobalUnlock(exampleStringPtr);
CloseClipboard();
}
}
getch();
return 0;
}
#包括“stdafx.h”
#包括“windows.h”
#包括“conio.h”
int main()
{
HWND owner=GetConsoleWindow();
//1.)将字符串复制到剪贴板
如果(打开剪贴板(所有者))
{
清空电路板();
//WCHAR*str=L“looong字符串示例”;
char*str=“looooong字符串示例”;
int-cch=strlen(str);
char*strprtr=(char*)GlobalAlloc(GMEM_可移动,(cch+1));
printf(“设置(段??)地址:%X\n”,strptr);
LPVOID lockedPtr=GlobalLock(strprtr);
printf(“锁定的设置地址:%X\n”,lockedPtr);
//抄袭
memcpy(锁定PTR、str、cch);
GlobalUnlock(strprtr);
//设置为剪贴板
SetClipboardData(CF_TEXT,strprtr);
//2.)在剪贴板未关闭时更改字符串-替换任何符号上的前10个字符
锁定PTR=全局锁定(strptr);
对于(int i=0;i<10;i++)
{
((char*)lockedPtr)[i]=50;
}
GlobalUnlock(strprtr);
//3.)获取字符串并确保字符串已更改
锁定PTR=全局锁定(strptr);
printf(“更改的字符串:%s\n”,lockedPtr);
GlobalUnlock(strprtr);
//4.)从剪贴板获取此字符串,并确保剪贴板已更改
strprpr=(char*)GetClipboardData(CF_TEXT);
printf(“获取地址:%X\n”,strprtr);
锁定PTR=全局锁定(strptr);
printf(“锁定的获取地址:%X\n”,lockedPtr);
printf(“获取的字符串:%s\n”,(char*)lockedPtr);
GlobalUnlock(strprtr);
CloseClipboard();
}
printf(“\n-------关闭并打开剪贴板-----------------\n”);
//5.)从剪贴板获取字符串
对于(int i=0;i<10;i++)
{
//睡眠(1000);
如果(打开剪贴板(所有者))
{
HANDLE exampleStringPtr=GetClipboardData(CF_TEXT);
printf(“获取地址:%X\n”,exampleStringPtr);
char*lockedPtr=(char*)GlobalLock(例如stringptr);
printf(“锁定的获取地址:%X\n”,lockedPtr);
printf(“获取的字符串:%s\n”,lockedPtr);
GlobalUnlock(示例StringPtr);
CloseClipboard();
}
}
getch();
返回0;
}
事实上,现在当我调用GetClipboardData时,我总是获得指向数据的相同指针。但有时它和我放入剪贴板的第一个字符串的锁定指针不同
虽然我在C++上写了这个测试,但我仍然有着早期写作的效果。
若我在调用SetClipboardData后更改了源内存块,然后尝试调用GetClipboardData,我将获得更改后的内存块。但当我关闭这个剪贴板,然后再次打开它时,我更改的内存块被一些信息覆盖了,我不知道,当我调用GetClipboardData时,内存块被恢复到初始状态,就好像我没有更改它一样
从哪里剪贴板“知道”如何恢复这个块,如果它没有它的副本,我改变了源块
我录制了一个小屏幕,显示内存在什么时候恢复了
SetClipboardData
将数据复制到给定的全局句柄中。关闭剪贴板后,应释放全局句柄(而不是在此之前)GetClipboardData
返回(内部)内存句柄;您应该将此句柄视为只读缓冲区。的文档非常清楚地表明,它不会复制您提供的数据-相反,剪贴板拥有数据句柄,尽管在关闭剪贴板之前您仍然可以从中读取,但一旦SetClipboardData()
呼叫已成功
一旦您关闭了剪贴板,您就不再拥有剪贴板,并且数据对象根本无法安全使用,即使用于读取,因为另一个进程可能已经更改了剪贴板的内容。您在关闭剪贴板后修改数据的测试是靠运气完成的,而不是因为它们本应如此
如果SetClipboardData成功,则系统拥有由
hMem参数。应用程序可能无法写入或释放数据
一旦所有权转移到系统,但它可以锁定和
读取数据,直到调用CloseClipboard函数。(修订)
必须先解锁内存,然后才能关闭剪贴板。)
编辑:因为你似乎对资源所有权的概念和未定义的行为有困难,也许这个类比会有所帮助
// allocate 1 byte of memory
char* ptr = malloc(sizeof(char));
// set the byte to the letter A
*ptr = 'A';
// free the memory
free(ptr);
// set the byte to B
*ptr = 'B';
// verify that the byte is set to B
printf("byte contains %c\n", *ptr);
// allocate another byte of memory
char* ptr2 = malloc(sizeof(char));
// are they the same byte? maybe
printf("byte contains %c - first was %lx, second is %lx\n", *ptr2, ptr, ptr2);
我希望你会发现这个代码是完全错误的。我们分配内存,写入它,释放它,然后,我们写入它并再次读取它。然而,如果您编译并运行这段代码,它很有可能会工作。第二次分配很有可能返回与第一次分配相同的地址。发生什么事了
这称为未定义的行为。语言没有定义在这种情况下会发生什么。当你释放内存时,你不再拥有它,你不能向它写入或读取它。如果它起作用,或者看起来起作用,那只是巧合,仅此而已。没有人能保证它会一直持续下去
//1.) Copying string to clipboard
if (WinAPI.OpenClipboard(owner))
{
WinAPI.EmptyClipboard();
IntPtr exampleStringPtr = Marshal.StringToHGlobalUni("Loooooooooooonng String Example");
Console.WriteLine("setting address: {0}", exampleStringPtr.ToInt32());
WinAPI.SetClipboardData(WinAPI.CF_UNICODETEXT, exampleStringPtr);
//2.) Change string while clipboard isn't closed - replace first 10 characters on one any symbol
for (int i = 0; i < 10; i++)
{
Marshal.WriteByte(exampleStringPtr + i, 50);
}
//3.) Obtain string and make sure that string was changed
Console.WriteLine("changed string: {0}", Marshal.PtrToStringUni(exampleStringPtr));
//4.) Get this string from clipboard and make sure that clipboard was changed
exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address of changed string: {0}", exampleStringPtr.ToInt32());
var lockedPtr = WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(exampleStringPtr);
WinAPI.GlobalUnlock(lockedPtr);
Console.WriteLine("obtained string: {0}", s);
WinAPI.CloseClipboard();
}
Console.WriteLine("\n-------Close and open clipboard------------------\n");
//5.) Getting string from clipboard
for (int i = 0; i < 100; i++)
if (WinAPI.OpenClipboard(owner))
{
IntPtr exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address: {0}", exampleStringPtr.ToInt32());
var lockedPtr = WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(lockedPtr);
WinAPI.GlobalUnlock(lockedPtr);
Console.WriteLine("obtained string: {0}", s);
WinAPI.CloseClipboard();
}
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
int main()
{
HWND owner = GetConsoleWindow();
//1.) Copying string to clipboard
if (OpenClipboard(owner))
{
EmptyClipboard();
//WCHAR *str = L"Loooong string example";
char *str = "Loooooooong string Example";
int cch = strlen(str);
char* strptr = (char*)GlobalAlloc(GMEM_MOVEABLE, (cch + 1));
printf("setting (segment??) address: %X \n", strptr);
LPVOID lockedPtr = GlobalLock(strptr);
printf("locked setting address: %X \n", lockedPtr);
// copy
memcpy(lockedPtr, str, cch);
GlobalUnlock(strptr);
// set to clipboard
SetClipboardData(CF_TEXT, strptr);
//2.) Change string while clipboard isn't closed - replace first 10 characters on one any symbol
lockedPtr = GlobalLock(strptr);
for (int i = 0; i < 10; i++)
{
((char*)lockedPtr)[i] = 50;
}
GlobalUnlock(strptr);
//3.) Obtain string and make sure that string was changed
lockedPtr = GlobalLock(strptr);
printf("changed string: %s \n", lockedPtr);
GlobalUnlock(strptr);
//4.) Get this string from clipboard and make sure that clipboard was changed
strptr = (char*)GetClipboardData(CF_TEXT);
printf("getting address: %X \n", strptr);
lockedPtr = GlobalLock(strptr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", (char*)lockedPtr );
GlobalUnlock(strptr);
CloseClipboard();
}
printf("\n-------Close and open clipboard------------------\n");
//5.) Getting string from clipboard
for (int i = 0; i < 10; i++)
{
//Sleep(1000);
if (OpenClipboard(owner))
{
HANDLE exampleStringPtr = GetClipboardData(CF_TEXT);
printf("getting address: %X \n", exampleStringPtr);
char* lockedPtr = (char*)GlobalLock(exampleStringPtr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", lockedPtr);
GlobalUnlock(exampleStringPtr);
CloseClipboard();
}
}
getch();
return 0;
}
// allocate 1 byte of memory
char* ptr = malloc(sizeof(char));
// set the byte to the letter A
*ptr = 'A';
// free the memory
free(ptr);
// set the byte to B
*ptr = 'B';
// verify that the byte is set to B
printf("byte contains %c\n", *ptr);
// allocate another byte of memory
char* ptr2 = malloc(sizeof(char));
// are they the same byte? maybe
printf("byte contains %c - first was %lx, second is %lx\n", *ptr2, ptr, ptr2);