2-ডি অ্যারেটি বাদ দিলে স্ট্রেলের অপ্রত্যাশিত অপ্টিমাইজেশন


28

আমার কোডটি এখানে:

#include <string.h>
#include <stdio.h>

typedef char BUF[8];

typedef struct
{
    BUF b[23];
} S;

S s;

int main()
{
    int n;

    memcpy(&s, "1234567812345678", 17);

    n = strlen((char *)&s.b) / sizeof(BUF);
    printf("%d\n", n);

    n = strlen((char *)&s) / sizeof(BUF);
    printf("%d\n", n);
}

জিসিসি 8.3.0 বা 8.2.1 ব্যতীত যে কোনও অপ্টিমাইজেশন স্তরটি ব্যবহার করে -O0, 0 2যখন আমি প্রত্যাশা করছিলাম তখন এই ফলাফলগুলি 2 2। সংকলক সিদ্ধান্ত নিয়েছে যে সীমারেখা strlenআবদ্ধ b[0]এবং তাই কখনও ভাগ করা মানকে সমান বা অতিক্রম করতে পারে না।

এটি কি আমার কোডের একটি বাগ বা সংকলকটিতে কোনও বাগ?

এই মান পরিষ্কারভাবে বানান আউট করা হয় না, কিন্তু আমার মনে হয়েছে পয়েন্টার উত্স মূলধারায় ব্যাখ্যা ছিল যে কোন বস্তুর জন্য X, কোড (char *)&Xএকটি পয়েন্টার যে সমগ্র উপর পুনরুক্তি করতে পারেন উৎপন্ন করা উচিত X- এই ধারণা রাখা উচিত এমনকি যদি Xআছে ঘটবে অভ্যন্তরীণ কাঠামো হিসাবে সাব-অ্যারে।

(বোনাস প্রশ্ন, এই নির্দিষ্ট অপ্টিমাইজেশন বন্ধ করার জন্য কোনও গিসি পতাকা রয়েছে?)



4
রেফ: আমার জিসিসি 7.4.0 2 2বিভিন্ন বিকল্পের অধীনে রিপোর্ট করে ।
chux - মনিকা 3 ই

2
@ তারা একই ঠিকানায় সমস্ত মানক গ্যারান্টি রয়েছে (কাঠামোর প্রাথমিক প্যাডিং থাকতে পারে না)
এমএম

3
@ ডেভিডর্যাঙ্কিন-রিইনস্টেটমোনিকা "ফলে চর (*) [8] এর সীমানা সীমিত হয়ে গেছে [0] তবে তবে আমি যতদূর পেলাম" আমি মনে করি এটি নখ করে। যেহেতু s.bএটি সীমাবদ্ধ b[0]এটি 8 টি অক্ষরের মধ্যেই সীমাবদ্ধ, এবং তাই দুটি বিকল্প: (1) 8 টি নন-অক্ষর অক্ষর, যা ইউবি, (2) একটি নাল অক্ষর রয়েছে যার মধ্যে লেনটি 8 এর চেয়ে কম, সুতরাং 8 দ্বারা বিভাজন শূন্য দেয়। সুতরাং (1) + (2) সংকলক একসাথে রাখলে উভয় ক্ষেত্রে একই ফলাফল দিতে ইউবি ব্যবহার করতে পারে
ব্যবহারকারী 2162550

3
যে & s == & s.b দেওয়া, ফলাফল আলাদা হতে পারে যে উপায় নেই। @ ব্যবহারকারী2162550 হিসাবে দেখানো হয়েছে, স্ট্র্লেন () বলা হয় না এবং সংকলকটির ফলাফল কী হতে পারে তা অনুমান করে, এমনকি গডবোল্ট.অর্গ / জেড / ডিএমসির্ডি যেখানে সংকলক এটি জানতে পারে না। এটি একটি সংকলক বাগ
এলে

উত্তর:


-1

কিছু সমস্যা আছে যা আমি দেখতে পাচ্ছি এবং সংকলক কীভাবে মেমরির বিন্যাসের সিদ্ধান্ত নেয় তার দ্বারা তারা প্রভাবিত হতে পারে।

    n = strlen((char *)&s.b) / sizeof(BUF);
    printf("%d\n", n);

উপরের কোডে s.b8 টি অক্ষরের একটি অ্যারের 23 প্রবেশপথের অ্যারে রয়েছে। যখন আপনি কেবল উল্লেখ করেন আপনি s.b23 বাইট অ্যারেতে প্রথম প্রবেশের ঠিকানা পেয়ে যাচ্ছেন (এবং 8 টি অক্ষরের অ্যারেতে প্রথম বাইট)। কোডটি যখন বলে &s.b, এটি অ্যারের ঠিকানার ঠিকানা জিজ্ঞাসা করছে। কভারগুলির অধীনে, সংকলকটি সম্ভবত কিছু স্থানীয় সঞ্চয়স্থান তৈরি করে সেখানে অ্যারের ঠিকানা সঞ্চয় করে এবং স্থানীয় স্টোরেজের ঠিকানা সরবরাহ করে strlen

আপনার কাছে 2 টি সম্ভাব্য সমাধান রয়েছে। তারা হ'ল:

    n = strlen((char *)s.b) / sizeof(BUF);
    printf("%d\n", n);

অথবা

    n = strlen((char *)&s.b[0]) / sizeof(BUF);
    printf("%d\n", n);

আমি আপনার প্রোগ্রামটি চালানোর এবং সমস্যাটি প্রদর্শনের চেষ্টা করেছি, তবে আমার কাছে যে কোনও -Oবিকল্পের সাথে আমার কাছে থাকা ঝাঁকুনি এবং জিসিসি সংস্করণ এখনও আপনার প্রত্যাশা অনুযায়ী কাজ করেছে। এটির মূল্যের জন্য, আমি x86_64-pc-linux-gnu- এ ক্ল্যাং সংস্করণ 9.0.0-2 এবং gcc সংস্করণ 9.2.1 চালাচ্ছি)।


-2

কোডটিতে ত্রুটি রয়েছে।

 memcpy(&s, "1234567812345678", 17);

উদাহরণস্বরূপ, ঝুঁকিপূর্ণ, যদিও এর সাথে খ এর সাথে শুরু হওয়া উচিত:

 memcpy(&s.b, "1234567812345678", 17);

দ্বিতীয় স্ট্রেন () এও ত্রুটি রয়েছে

n = strlen((char *)&s) / sizeof(BUF);

উদাহরণস্বরূপ, হওয়া উচিত:

n = strlen((char *)&s.b) / sizeof(BUF);

স্ট্রিং এসবি, যদি সঠিকভাবে অনুলিপি করা হয় তবে 17 অক্ষর দীর্ঘ হওয়া উচিত। স্ট্রাইকগুলি সারিবদ্ধ থাকলে কীভাবে মেমরিতে স্ট্রোকগুলি সংরক্ষণ করা হয় তা নিশ্চিত নয়। আপনি কি পরীক্ষা করে দেখেছেন যে এসবিতে কপিরাইট করা 17 টি অক্ষর রয়েছে?

সুতরাং একটি স্ট্রেলেন (এসবি) 17 টি দেখায়

% D পূর্ণসংখ্যা হিসাবে প্রিন্টফ কেবল পূর্ণসংখ্যার সংখ্যা দেখায় এবং ভেরিয়েবল n কে পূর্ণসংখ্যা হিসাবে ঘোষণা করা হয়। আকারের (বিইউএফ) হতে হবে 8

সুতরাং 8 (17/8) দ্বারা বিভক্ত 17 টি হিসাবে 2 টি মুদ্রণ করা উচিত এন হিসাবে পূর্ণসংখ্যা হিসাবে ঘোষিত হয়েছে। যেহেতু মেমকিটি ডেটা অনুলিপি করার জন্য এবং এসবিতে ব্যবহার করার জন্য ব্যবহৃত হত, আমি অনুমান করব যে এটি মেমরির প্রান্তিককরণের সাথে করতে পারে; এটি মনে করে যে এটি একটি 64 বিট কম্পিউটার, একটি মেমরির ঠিকানায় 8 টি অক্ষর থাকতে পারে।

উদাহরণস্বরূপ, ধরে নেওয়া যাক যে পরবর্তী "ফ্রি স্পেস" প্রান্তিককরণ না করে, কেউ ম্যালোক (1) বলেছেন has

দ্বিতীয় স্ট্রেন কলটি, সঠিক নম্বরটি দেখায়, কারণ স্ট্রিং কপিটি sb এর পরিবর্তে এস স্ট্রাক্টে করা হয়েছিল

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