একাধিক মাত্রিক অ্যারে থেকে গণনা মান কেন নিজের সমান নয়?


151

বিবেচনা:

using System;

public class Test
{
    enum State : sbyte { OK = 0, BUG = -1 }

    static void Main(string[] args)
    {
        var s = new State[1, 1];
        s[0, 0] = State.BUG;
        State a = s[0, 0];
        Console.WriteLine(a == s[0, 0]); // False
    }
}

কিভাবে এই ব্যাখ্যা করা যেতে পারে? এটি x86 জেআইটি চলাকালীন ভিজ্যুয়াল স্টুডিও 2015-এ ডিবাগ বিল্ডে ঘটে। এক্স 64 জেআইটিতে একটি রিলিজ বিল্ড বা চলমান প্রত্যাশার মতো সত্য মুদ্রণ করে।

কমান্ড লাইন থেকে পুনরুত্পাদন করতে:

csc Test.cs /platform:x86 /debug

( /debug:pdbonly, /debug:portableএবং /debug:fullএছাড়াও পুনরুত্পাদন।)


2
ideone.com/li3EzY এটি সত্য। নেট সংস্করণ, আইডিই, সংকলক
ব্যাকস

1
একই অবস্থা. তবে প্রকল্পের সেটিংসের সাথে ঝাঁকুনির পরে আমি বুঝতে পেরেছি যে "বিল্ড" ট্যাবটিতে "32 বিট পছন্দসই" চেকবক্সটি আনচেক করা এটিকে উদ্দেশ্য হিসাবে কাজ করে - সত্যে ফিরে আসে। সুতরাং, এটি আমার কাছে একটি ওউডাব্লু 64 ইস্যুর মতো দেখাচ্ছে।
দিমিত্রি রোটে

2
দেখে মনে হচ্ছে আপনি ফ্রেমওয়ার্কটিতে একটি বাগ নির্দেশ করেছেন pointed
ফ্যাবিয়ান পেরোননেট

1
মজার বিষয় হল, ভাঙা কোডটি চালিয়ে ildasmতারপরে এটি ilasm"ঠিক করে" ...
জন স্কিটি

2
/debug=IMPLপতাকা পাতার এটিকে ভাঙা অবস্থায়; /debug=OPTএটি "স্থির করে"।
জন স্কিটি

উত্তর:


163

.NET 4 x86 জিটারে আপনি একটি কোড প্রজন্মের বাগ খুঁজে পেয়েছেন। এটি খুব অস্বাভাবিক একটি, কোডটি অনুকূলিত না হলে এটি ব্যর্থ হয়। মেশিন কোডটি এর মতো দেখাচ্ছে:

        State a = s[0, 0];
013F04A9  push        0                            ; index 2 = 0
013F04AB  mov         ecx,dword ptr [ebp-40h]      ; s[] reference
013F04AE  xor         edx,edx                      ; index 1 = 0
013F04B0  call        013F0058                     ; eax = s[0, 0]
013F04B5  mov         dword ptr [ebp-4Ch],eax      ; $temp1 = eax 
013F04B8  movsx       eax,byte ptr [ebp-4Ch]       ; convert sbyte to int
013F04BC  mov         dword ptr [ebp-44h],eax      ; a = s[0, 0]
        Console.WriteLine(a == s[0, 0]); // False
013F04BF  mov         eax,dword ptr [ebp-44h]      ; a
013F04C2  mov         dword ptr [ebp-50h],eax      ; $temp2 = a
013F04C5  push        0                            ; index 2 = 0
013F04C7  mov         ecx,dword ptr [ebp-40h]      ; s[] reference 
013F04CA  xor         edx,edx                      ; index 1 = 0
013F04CC  call        013F0058                     ; eax = s[0, 0]
013F04D1  mov         dword ptr [ebp-54h],eax      ; $temp3 = eax 
                                               ; <=== Bug here!
013F04D4  mov         eax,dword ptr [ebp-50h]      ; a == s[0, 0] 
013F04D7  cmp         eax,dword ptr [ebp-54h]  
013F04DA  sete        cl  
013F04DD  movzx       ecx,cl  
013F04E0  call        731C28F4  

প্রচুর টেম্পোরারি এবং কোড ডুপ্লিকেশন সহ একটি প্লডডিং অ্যাফেয়ার, এটি অনিচ্ছাকৃত কোডের জন্য সাধারণ। 013F04B8 এ দেওয়া নির্দেশটি উল্লেখযোগ্য, সেখান থেকে এসবিটি থেকে 32-বিট পূর্ণসংখ্যায় রূপান্তর ঘটে। অ্যারে প্রাপ্তকারী সহায়তা ফাংশন 0x0000000FF, State.BUG এর সমান ফিরে এসেছিল এবং মানটির সাথে তুলনা করার আগে এটি -1 (0xFFFFFFF) এ রূপান্তর করা দরকার। MOVSX নির্দেশনা একটি সাইন এক্সটেনশন নির্দেশ।

013F04CC এ আবার একই ঘটনা ঘটে তবে এবার আর নেই এবার একই রূপান্তর করার জন্য এমওভিএসএক্স নির্দেশ । চিপসটি এখানেই পড়ে যায়, সিএমপি নির্দেশনা 0xF00FFFFF 0x000000FF এর সাথে তুলনা করে এবং এটি মিথ্যা। সুতরাং এটি বাদ দেওয়ার একটি ত্রুটি, কোড জেনারেটর একই স্কাইটি ইন্ট রূপান্তর করতে আবার এমওভিএসএক্স নির্গত করতে ব্যর্থ হয়েছিল।

এই বাগটি সম্পর্কে বিশেষত অস্বাভাবিক বিষয়টি হল আপনি যখন অপটিমাইজারটি সক্ষম করবেন তখন এটি সঠিকভাবে কাজ করে, এটি এখন উভয় ক্ষেত্রেই এমওভিএসএক্স ব্যবহার করতে জানে।

এই বাগটি এত দিন ধরে সনাক্ত করা যায় না এমন সম্ভাব্য কারণ হ'ল এনুমের বেস ধরণ হিসাবে এসবিটি ব্যবহার। বেশ বিরল। বহুমাত্রিক অ্যারে ব্যবহার করা যেমন উপকরণ তেমনি সংমিশ্রণটি মারাত্মক।

অন্যথায় আমি বলব একটি সুন্দর সমালোচনা বাগ। এটি কতটা বিস্তৃত হতে পারে তা অনুমান করা শক্ত, আমার কাছে কেবল পরীক্ষার জন্য 4.6.1 x86 জিটার রয়েছে। X64 এবং 3.5 x86 জিটারটি খুব আলাদা কোড উত্পন্ন করে এবং এই বাগটি এড়ায়। অস্থায়ী কর্মক্ষেত্রটি চালিয়ে যাওয়া হ'ল এনবাইজ বেস টাইপ হিসাবে এসবিট সরিয়ে এবং এটি ডিফল্ট, ইনট হিসাবে দেওয়া হোক , তাই কোন চিহ্ন এক্সটেনশন প্রয়োজন।

আপনি সংযোগ.মিক মাইক্রোসফট.কম এ বাগটি ফাইল করতে পারেন, এই প্রশ্ন + এটির সাথে লিঙ্ক করার জন্য তাদের যা জানা দরকার তা তাদের জানাতে যথেষ্ট হওয়া উচিত। আপনি সময় না নিতে চাইলে আমাকে জানান এবং আমি এটি যত্ন নেব।


33
ভালো, দৃ data় ডেটা যেমন একটি অদ্ভুত সমস্যার সঠিক কারণ, পড়তে সর্বদা আনন্দ, +1।
লাসে ভি কার্লসেন

11
দয়া করে কানেক্ট.টি.মাইক্রোসফট.কম নিবন্ধটিতে একটি লিঙ্ক পোস্ট করুন যাতে আমরা এটির জন্য ভোট দিতে পারি।
হ্যান্স প্যাস্যান্ট

আমি মনে করি byteপরিবর্তে ব্যবহার করা sbyteখুব ভাল হওয়া উচিত এবং যদি আপনি একটি ওআরএম বলুন যেখানে আপনি ডাটাবেসে আপনার পতাকাগুলি অতিরিক্ত স্থান গ্রহণ করতে চান না তখন যদি সত্য কোডটি ব্যবহার করা হয় তবেই ভাল।
ভু

6
আমি সংযোগের পরিবর্তে ডটনেট / কোরসিএলআরটিতে বাগটি পোস্ট করতাম , আপনি সরাসরি জেআইটি ডিভাসে উঠবেন
লুকাস ট্রাজেনিউস্কি

8
আমি মাইক্রোসফ্টে জেআইটি দলের একজন দেব। আমি বাগটি পুনরুত্পাদন করেছি এবং এটির জন্য অভ্যন্তরীণভাবে একটি সমস্যা খুলেছি (শিপিং x86 জেআইটি এখনও গিথুবে খোলা নেই)। এটি কখন ঠিক করা হবে তার সময়ের ক্ষেত্রে, আমি প্রত্যাশা করি যে আমরা এই ফিক্সটি সরঞ্জামগুলির পরবর্তী বড় রিলিজের অন্তর্ভুক্ত করব। যদি এই বাগটি ব্যবসায়িক প্রভাব ফেলতে থাকে এবং আপনার আগে ঠিক করার প্রয়োজন হয় তবে দয়া করে সংযোগ (সংযুক্ত.মাইক্রোসফট.কম) সমস্যাটি ফাইল করুন যাতে আমরা প্রভাব দেখতে পারি এবং দ্রুত আপনাকে ঠিক করার জন্য আমাদের কী বিকল্প থাকতে পারে।
রাসেল সি হ্যাডলি

8

আসুন ওপির ঘোষণাকে বিবেচনা করুন:

enum State : sbyte { OK = 0, BUG = -1 }

যেহেতু বাগটি তখনই ঘটে যখন BUGনেতিবাচক হয় (-128 থেকে -1 পর্যন্ত) এবং রাজ্য স্বাক্ষরিত বাইটের এনাম হয় আমি ধরে নিতে শুরু করি যে কোনও জায়গায় cast সমস্যা রয়েছে।

আপনি যদি এটি চালান:

Console.WriteLine((sbyte)s[0, 0]);
Console.WriteLine((sbyte)State.BUG);
Console.WriteLine(s[0, 0]);
unchecked
{
    Console.WriteLine((byte) State.BUG);
}

এটি আউটপুট হবে:

255

-1

বাগ

255

একটি কারণ যে, আমি উপেক্ষা করি (এখন পর্যন্ত) s[0, 0] মূল্যায়ন করার পূর্বে একটি বাইট এবং কেন এটা দাবি করে যে যে এর নিক্ষেপ করা হয় a == s[0,0]মিথ্যা।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.