Войти
ФлеймФорумПрограммирование

Гадский clipboard падает.

Страницы: 1 2 3 4 5 Следующая »
#0
(Правка: 20:00) 16:21, 20 фев. 2020

64 bit программа.

У меня есть два threads.
Во втором по клавише "V" делаю вызов функции вставить в windows clipboard.

Так вот 1 раз срабатывает. И в текстовый файл я по control+V вставляю слово "past"
Иногда второй раз срабатывает, но и может падать.
А третий раз точно крашится моя прога.

Убрал вставить в windows clipboard и крашей нет. То есть точно clipboard выделывается.

Crash отметил места где происходят падения. Отловил MessageBox- мо
Вот код моей clipboard:

hr = GlobalAlloc(GMEM_DDESHARE,1024);//crash
if (hr ==0) return 0;

clip = OpenClipboard(NULL);//crash
if (clip == 0) return 0;

EmptyClipboard();
SetClipboardData(CF_TEXT,"past");
CloseClipboard();
GlobalFree(hr);

#1
16:46, 20 фев. 2020

ronniko
> SetClipboardData(CF_TEXT,"past");
Что это такое во втором параметре?

#2
(Правка: 16:56) 16:50, 20 фев. 2020

SetClipboardData(CF_TEXT,"past");
Я как псевдо код дал.
Там адрес текста(тот что hr от GlobalAlloc) в место "past".
В адрес от GlobalAlloc заношу "past"

SetClipboardData(CF_TEXT,hr);

#3
(Правка: 16:57) 16:56, 20 фев. 2020

ronniko
> if (hr =0) return 0;
> if (clip = 0) return 0;
=

#4
(Правка: 17:00) 16:58, 20 фев. 2020

Типа не два == ?

Это псевдо код я же на Fasme делаю.
А псевдо код показал , что бы показать что делает моя clip функция.

#5
16:59, 20 фев. 2020

ronniko
> Это псевдо код я же на Fasme делаю.
так мы тебе и поверили )))

#6
(Правка: 17:02) 17:01, 20 фев. 2020
macro ClipboardSetDat chDt { local ll2
      invoke      GlobalAlloc,GMEM_DDESHARE,1024     
      test        rax,rax
      jz          ll2      ;если ноль то прыгает на ll2

      mov         rsi,rax

      CopyTextDo  chDt,eax,0
      Msg  'ClipBoard 1'

      invoke      OpenClipboard,0
      test   rax,rax
      jz     ll2      ;если ноль то прыгает на ll2
      Msg  'ClipBoard 2'

      invoke      EmptyClipboard
      invoke      SetClipboardData,CF_TEXT,rsi
      invoke      CloseClipboard
      invoke      GlobalFree,rsi
      
      Msg  'ClipBoard 3'
ll2:  Msg  'ClipBoard end'
      }                     
#7
(Правка: 17:10) 17:06, 20 фев. 2020

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-win… clipboarddata

If SetClipboardData succeeds, the system owns the object identified by the hMem parameter. The application may not write to or free the data once ownership has been transferred to the system, but it can lock and read from the data until the CloseClipboard function is called. (The memory must be unlocked before the Clipboard is closed.) If the hMem parameter identifies a memory object, the object must have been allocated using the function with the GMEM_MOVEABLE flag.

ronniko
> GlobalFree(hr);
Мне кажется, кто-то просто забыл свериться с доками.

Там по ссылкам, кстати, даже гайд с примерами есть.

#8
17:09, 20 фев. 2020

ronniko
у меня твой код работает (если не использовать "past"). Вероятнее всего проблема в fasm'е

#9
(Правка: 17:12) 17:09, 20 фев. 2020

Delfigamer
Thanks ! I try it :)

Сразу crash с флагом GMEM_MOVEABLE

#10
(Правка: 17:13) 17:12, 20 фев. 2020

ronniko
тут еще FROL пишет у себя на сайте, что надо фиксировать память с помощью GlobalLock(HGLOBAL hglb);

Для получения доступа к полученному блоку памяти его необходимо зафиксировать, вызвав функцию GlobalLock

http://www.frolov-lib.ru/books/bsp/v13/ch2_3.htm
#11
17:17, 20 фев. 2020

Судя по примеру, должно быть что-то вроде такого:

Status SetClipboard(std::string const& text)
{
    if (text.empty()) {
        return Status::Success;
    }
    if (!OpenClipboard(0)) {
        return Status::Failure;
    }
    EmptyClipboard();
    HANDLE bufhandle = GlobalAlloc(GMEM_MOVEABLE, text.size() + 1);
    {
        void* bufptr = GlobalLock(bufhandle);
        memcpy(bufptr, text.data(), text.size() + 1);
        GlobalUnlock(bufhandle);
    }
    SetClipboardData(CF_TEXT, bufhandle);
    CloseClipboard();
    return Status::Success;
}

#12
(Правка: 17:18) 17:17, 20 фев. 2020

GlobalLock когда мы хотим залить данные с win clipboard к себе.

Но точно на 100% не уверен.

#13
(Правка: 17:26) 17:26, 20 фев. 2020

GlobalAlloc резервирует память, но не показывает её процессу сразу. Вместо этого возвращается дескриптор.
Чтобы дорваться до содержимого этой памяти, нужно её залочить через GlobalLock. Только тогда буфер отображается в адресное пространство процесса, и функция возвращает адрес этого отображения. После записи буфер освобождается через GlobalUnlock. После этого другие процессы могут отображать тот же буфер у себя и считать из него содержимое.
А поскольку SetClipboardData забирает владение дескриптором себе, то оставшийся у процесса HANDLE становится недействительным, и попытка что-то с ним сделать - залочить или освободить - приведёт к ругательствам ОС.
Ну а поскольку HANDLE - это не указатель, то попытка записать что-то по его значению - прямая дорога к затёртой памяти.

Можно ещё сравнить с тем, как работают буферы в DirectX и OpenGL - сначала аллоцируется объект буфера, и уже через него записывается содержимое.

#14
(Правка: 17:28) 17:26, 20 фев. 2020

Delfigamer да твой код работает.
Я сделал 20 раз нажатие клавишы "V" не упало.

Спасибо.

Получается в GlobalAlloc(GMEM_DDESHARE,1024);
флаг GMEM_DDESHARE сразу автоматом делает GlobalAlloc\GlobalUnlock

Страницы: 1 2 3 4 5 Следующая »
ФлеймФорумПрограммирование