Hatalar, hatalar, sorular - sayfa 2576

 
Vict :

Çok güzel örnekleriniz var, her şeyi kaldırdılar, UB'yi bıraktılar (dize değişmezlerinin değiştirilmesi) ve herkes telepati yapmalı. Bir tür mantıklı tavsiyeye güveniyorsanız, minimum çalışma kodunu (her iki tarafta da) verin, aksi takdirde sadece gevezelik olur.

Örnek, soruna neden olan yeri, yani wchar_t* işaretçisinin mql dizesine kopyalanmasındaki sorunu gösterir.
Sorunla ilgili olmayan kodun geri kalanı bir payload taşımaz, çünkü yalnızca verinin orada olup olmadığını kontrol eder, sonra okuruz vb.
Neden bir örnek olarak yazıp sorunun özünü çöpe atıyorsunuz, basitleştirilmiş bir kodla bile çoğu kişi sorunun özünün ne olduğunu anlamayacak.
getData() öğesinin bir FrameOpcode okuyan ve elde edilen verileri const wchar_t* türünde bir işaretçi olarak döndüren bir ağ işlevi olduğunu anlayın.

Herkes wcscpy(out, data) basit fonksiyonunun kopyaladığını bilir.   const wchar_t* string, wchar_t* string'e ve karakter uzunluğunu terminal sıfıra kadar otomatik olarak sayar const wchar_t*
Hatanın göründüğü yer burasıdır, mql-ovsky dizesi kopyalanan dizeyi wchar_t* doğru bir şekilde kabul etmez , soru şu ki bu neden olabilir? İşlev, terminal sıfırını otomatik olarak belirlerse.
Renat'ın makalesinde, dizeler memcpy aracılığıyla bayt boyutu hatasıyla kopyalanıyor. Belki de aynı yaklaşım, mql dize türünü oluşturmak için terminal kodunun kendisinde kullanılır.
Görüyorsunuz,
memcpy sadece dizeleri kopyalamak için uygun değil, aynı zamanda aktarılan baytların boyutunda bir hata ile pürüzlü verilere yol açar.
Dizeleri kopyalamak için, bunun için wcscpy, wcsncpy, vb. gibi C'ye özgü başka işlevler vardır.
Evet ve Renat'ın kendisi şubelerden birinde, dizelerle çalışmayı yakında tamamen elden geçireceklerini yazdı, görünüşe göre sorun biliniyor, ancak nedense tanımladığım soruna yanıt olarak sessizlik var.

Karşılaştırma için, wchar_t* işaretçisinin ve wchar_t basit türünün baytlarının boyutu

Dosyalar:
1.PNG  83 kb
 
Roman :

Elbette, yanıt olarak bütün bir ayak örtüsü yazmak, getData() yerine bir şey koymak yerine normal tekrarlanabilir bir testten daha kolaydır. UB, UB'deyse ve sonuçlar yanlışsa ne bekliyorsunuz:

memcpy(cp,to,wcslen(to)* sizeof (wchar_t));   // в этой строке должен быть указатель sizeof(wchar_t *)

her şey orada. Dizeler hakkındaki fikirlerinizle ilgili bir sorun var, bu nedenle hatalar.

 
Vict :

Elbette, yanıt olarak bütün bir ayak örtüsü yazmak, getData() işlevini bir şeyle değiştirmek yerine tekrarlanabilir normal bir testten daha kolaydır. UB, UB'deyse ve sonuçlar yanlışsa ne bekliyorsunuz:

her şey orada. Dizeler hakkındaki fikirlerinizle ilgili bir sorun var, bu nedenle hatalar.

Yeniden üretilebilir bir kod sağlamanın bir yolu yoktur, çünkü bunun üçüncü taraf kitaplıkları kullanan bir dll olduğunu kendiniz anlarsınız.
Örnekte neden bir hata olduğuna karar verdiğim hakkında.
memcpy (cp,to,wcslen(to)* sizeof (wchar_t)); // bu satır sizeof(wchar_t *) işaretçisi içermelidir

İşaretçi olmadan bir işlev kullanmak,

memcpy( out , data, wcslen(data) * sizeof (wchar_t));

sonra satırın sonu fazladan karakterlerle yüzmeye başlar. Resimdeki satırın sonuna bakın.
Ve wchar_t * dizesini bir işaretçi olarak kopyalarsak, türün boyutunu değil işaretçinin boyutunu geçmemiz gerekir.

Ve bir işaretçi kullanırsam,

memcpy( out , data, wcslen(data) * sizeof (wchar_t*));

o zaman satır, fazladan karakterler olmadan açıktır.
Her şey yoluna girecek, ancak her iki durumda da, bir nedenden dolayı, ayrıştırma ile ilgili başka bir sorun var, sonra çizgiler akıyor, sonra boşluklar.

Ve eğer bu işlevi kullanırsam, o zaman hiçbir şey akmaz, her şey iyi ayrıştırılır, satırın sonunda yalnızca bir fazladan karakter vardır, sonra görünür ve kaybolur.

wcsncpy(out, data, wcslen(data));

Bu yüzden, bir neden olabilecek bir sürü seçeneği gözden geçiriyorum, ancak sizeof'ta bir işaretçi olmadan memcpy kullanmak, sonuç ekranda görülebilir.

Ayrıca alınan wchar_t * dizesini, var olsun veya olmasın, bir terminal sıfır için kontrol etmek istiyorum.
Bunu nasıl yapabilirim?

Dosyalar:
 
İşaretçi olmadan bir işlev kullanmak,

burada sonunda \0 olmadan kalacak

Ve bir işaretçi kullanırsam,

burada sınırların dışındasın

Ve eğer bu işlevi kullanırsam, o zaman hiçbir şey akmaz, her şey iyi ayrıştırılır, satırın sonunda yalnızca bir fazladan karakter vardır, sonra görünür ve kaybolur.

yine dışarı \0 olmadan bırakılacaktır. rıhtımlara bakın

wcsncpy, wcsncpy_s

...

src dizesinin tamamı kopyalanmadan önce sayıya ulaşılırsa, sonuçtaki geniş karakter dizisi boş sonlandırılmaz.

...

ZY: Genel olarak hatlarla iletişim kuramıyor musunuz? dizileri wchar_t içine kaydedin ve onları sürün ve gerekirse µl içinde dizeye dönüştürün https://www.mql5.com/ru/docs/convert/shortarraytostring

 
Vict :

ZY: Genel olarak hatlarla iletişim kuramıyor musunuz? dizileri wchar_t içine kaydedin ve onları sürün ve gerekirse µl'nin içinde bir dizgeye dönüştürün

Oh, senkyu )) wcsncpy'nin sıfırı kestiği ipucu için.
Evet, dizileri en sona bıraktım, pointer ile olmuyorsa dizi kullanacağım.

 

Forum motoru tek bir resimden gönderi yapmanıza izin vermiyor. Metin girişi gerektirir.

Bir boşluk koymalısın.

 
fxsaber :

Forum motoru tek bir resimden gönderi yapmanıza izin vermiyor. Metin girişi gerektirir.

Bir boşluk koymalısın.

Her şey mantıklı görünüyor: bu bir forum ve asıl şey metin. Ve resim ne kadar uygulanır. Burası bir resim mezarlığı değil.

 

kodu tamamladı, MT4/5'te çalışıyor, küçük bir sürprizle karşılaştı

MQL4'te TesterStop() 'un yerini ne alabilir?

?

 
Igor Makanu :

MQL4'te TesterStop()'un yerini ne alabilir?

UzmanKaldır .

 
fxsaber :

UzmanKaldır.

Bu seçeneği biliyorum ama ExpertRemove (0 Market uzmanları için kullanılamaz, belki bir araya gelip Market'e koyarım, tekrar yapmam gerekecek şeklinde mesajlar gördüm.

genel olarak iki durumda TesterStop() kullanıyorum:

- optimize edici günlüğünü gizlemek için INIT_PARAMETERS_INCORRECT yerine

- bir sipariş açmak için yeterli para yoksa, siparişi açmam, ancak testi tamamlarım, böylece optimizasyon daha hızlı ilerler