এই কোডটি কেন 64৪-বিট আর্কিটেকচারে সেগফল্ট করে তবে 32-বিটের উপর কাজ করে?


112

আমি নিম্নলিখিত সি ধাঁধাটি পেরিয়ে এসেছি:

প্রশ্ন: নীচের প্রোগ্রামটি কেন আইএ -৪৪ তে সেগফল্ট করে, তবে আইএ -32-তে কাজ করে?

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

আমি জানি যে intএকটি 64 বিট মেশিনের আকার পয়েন্টারের আকারের মতো নাও intহতে পারে ( 32 বিট এবং পয়েন্টার 64 বিট হতে পারে)। তবে উপরের প্রোগ্রামের সাথে এটি কীভাবে সম্পর্কিত তা আমি নিশ্চিত নই। কোন ধারনা?


49
এটি stdlib.hঅন্তর্ভুক্ত না করার মতো নির্বোধ কিছু ?
ব্যবহারকারী 786653

3
এই কোডটি আমার 64 বিট মেশিনে সূক্ষ্মভাবে চলে। এমনকি যদি আপনি #include stdlib.h(
ম্যালোকের

1
ডি আহা! @ ব্যবহারকারী 786653 গুরুত্বপূর্ণ বিট পেরেক করেছে। সহ #include <stdlib.h>, এটি পুরোপুরি খুঁজে পাওয়া যায়, তবে এটি প্রশ্নে আসে না।

8
@ ডেলানান - যদিও এটির মতো কাজ করতে হবে না, এটি বৈধভাবে একটি প্ল্যাটফর্মে ব্যর্থ হতে পারে যেখানে sizeof(int) == sizeof(int*)উদাহরণস্বরূপ পয়েন্টারগুলি যদি ফিরে আসে intকলিং কনভেনশনে ভিন্ন রেজিস্টার হিসাবে ।
ফ্লেক্সো

7
একটি C99 পরিবেশে, সংকলকটি আপনাকে অন্তর্নিহিত ঘোষণার বিষয়ে কমপক্ষে একটি সতর্কতা দিচ্ছে malloc()। জিসিসি বলেছেন: warning: incompatible implicit declaration of built-in function 'malloc'খুব।
জোনাথন লেফলার

উত্তর:


130

int*মাস্কগুলিতে নিক্ষেপ করা এই সত্যটি যে যথাযথ ছাড়া #includeরিটার্নের ধরণটি mallocধরে নেওয়া হয় int। আইএ -৪৪ এর সাথে ঘটে sizeof(int) < sizeof(int*)যা এই সমস্যাটিকে স্পষ্ট করে তোলে।

(এটিও নোট করুন যে অপরিবর্তিত আচরণের কারণে এটি এখনও এমন প্ল্যাটফর্মে ব্যর্থ হতে পারে যেখানে sizeof(int)==sizeof(int*)সত্য রয়েছে, উদাহরণস্বরূপ যদি কলিং কনভেনশনটি পূর্ণসংখ্যার চেয়ে পয়েন্টারগুলি ফেরত দেওয়ার জন্য বিভিন্ন রেজিস্টার ব্যবহার করে)

Comp.lang.c প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী একটি এন্ট্রি আলোচনা হয়েছে কেন থেকে ফেরত ভোটদান mallocপ্রয়োজন হয় না এবং সম্ভাব্য খারাপ


5
যথাযথ # অন্তর্ভুক্ত ব্যতীত, ফিরে আসা ধরণের ম্যালোককে কোন আন্ত হিসাবে ধরা হয় কেন?
ব্যবহারকারী 7

11
@ ডব্লিউটিপি - যা সর্বদা newসি ++ তে ব্যবহার করার এবং সি -++ সংকলক নয় সর্বদা সি সংকলক দিয়ে সি সংকলন করার একটি ভাল কারণ ।
ফ্লেক্সো

6
@ ইউজার - - এটি নিয়ম। কোনও রিটার্নের টাইপ এটি ধরে না intথাকলে তা বলে ধরে নেওয়া হয়
ফ্লেক্সো

2
@ ভ্লাদ - ঠিক এই কারণেই নিখুঁত ঘোষণার উপর নির্ভর না করে সর্বদা কার্যকারিতা ঘোষণা করা ভাল ধারণা । (এবং এর থেকে malloc
রিটার্নটি

16
@ ইউজার:: "আমাদের কাছে একটি পয়েন্টার পি রয়েছে (64৪ আকারের) যা মেমরির 32 বিটগুলিতে নির্দেশ করছে" - ভুল। মলোক দ্বারা বরাদ্দকৃত ব্লকের ঠিকানাটি ক এর জন্য কলিং কনভেনশন অনুযায়ী ফিরিয়ে দেওয়া হয়েছিল void*। তবে কলিং কোডটি ফাংশনটি ফিরে আসার কথা চিন্তা করে int(যেহেতু আপনি এটি অন্যথায় না বলার পছন্দ করেছেন), সুতরাং এটি কলটির কনভেনশন অনুযায়ী রিটার্নের মানটি পড়ার চেষ্টা করে int। অতএব অগত্যা বরাদ্দ মেমরি নির্দেশ pকরে না । এটি ঠিক তাই আইএ 32 এর জন্য কাজ করার কারণ ঘটেছে কারণ একটি intএবং একটি void*একই আকারের, এবং একই পথে ফিরে এসেছে। আইএ 64 এ আপনি ভুল মান পাবেন value
স্টিভ জেসোপ

33

সম্ভবত আপনি কারণ হিসাবে শিরোলেখ ফাইলটি অন্তর্ভুক্ত করছেন নাmalloc এবং সংকলক সাধারণত আপনাকে এ সম্পর্কে সতর্ক করে দেবে, আপনি স্পষ্টতই রিটার্ন মানটি কাস্ট করছেন এর অর্থ হচ্ছে আপনি কী করছেন তা আপনার জানাচ্ছেন।

এর অর্থ সংকলকটি প্রত্যাশা করে যে এটির কোনও intপ্রত্যাবর্তন হবে mallocযা থেকে এটি পরে কোনও পয়েন্টারে যায়। যদি তারা বিভিন্ন আকারের হয় তবে এটি আপনাকে শোকের কারণ হতে পারে।

এই জন্যই আপনি কখনো নিক্ষেপ mallocসি দ্য মধ্যে রিটার্ন void*এটি আয় পরোক্ষভাবে সঠিক ধরনের পয়েন্টার রূপান্তরিত হবে (যতক্ষণ না আপনি হেডার যে ক্ষেত্রে এটি সম্ভবত সম্ভাব্য অসুরক্ষিত int- সম্পর্কে সতর্ক করে দিয়েছি হবে অন্তর্ভুক্ত না টু-পয়েন্টার রূপান্তর)।


নিষ্পাপ শোনার জন্য দুঃখিত, তবে আমি সর্বদা ধরে নিয়েছি যে malloc একটি শূন্য পয়েন্টার দেয় যা একটি উপযুক্ত টাইপ করা যেতে পারে। আমি কোনও সি প্রোগ্রামার নই এবং তাই আরও কিছু বিশদ প্রশংসা করব।
ব্যবহারকারী 7

5
@ ইউজার without: # অন্তর্ভুক্ত <stdlib.h> সি সংকলকটি ম্যালোকের রিটার্ন মানটি একটি int হিসাবে ধরে নেয়।
শাশং

4
@ ইউজার 7: অকার্যকর পয়েন্টারটি beালাই করা যেতে পারে, তবে সি তে এটির দরকার নেই কারণ এটি void *অন্য কোনও পয়েন্টার প্রকারকে স্পষ্টভাবে রূপান্তর করতে পারে। int *p = malloc(sizeof(int))যথাযথ প্রোটোটাইপ সুযোগে থাকলে এবং ব্যর্থ হলে এটি ব্যর্থ হয় (কারণ ফলাফলটি অনুমান করা হয় int)। কাস্টের সাহায্যে উভয়ই সংকলন করত এবং পরবর্তীকালে ত্রুটি হতে পারে sizeof(int) != sizeof(void *)

2
@ ইউজার But তবে আপনি যদি stdlib.hএটি অন্তর্ভুক্ত না করেন তবে সংকলকটি জানে না mallocএবং এটির ফেরতের প্রকারও নয় । সুতরাং এটি কেবল intডিফল্ট হিসাবে ধরে নেওয়া হয়।
খ্রিস্টান রাউ

10

এ কারণেই আপনি অনুপস্থিত প্রোটোটাইপ সম্পর্কে সতর্কতা ছাড়াই কখনই সংকলন করবেন না।

এ কারণেই আপনি কখনও সিতে ম্যালোক রিটার্ন কাস্ট করেন না

+ালাই সি ++ সামঞ্জস্যের জন্য প্রয়োজন। এটিকে বাদ দেওয়ার খুব কম কারণ রয়েছে (পড়ুন: এখানে কোনও কারণ নেই)।

সি ++ সামঞ্জস্যতা সবসময় প্রয়োজন হয় না, এবং কয়েকটি ক্ষেত্রে মোটেই সম্ভব নয়, তবে বেশিরভাগ ক্ষেত্রে এটি খুব সহজেই অর্জন করা যায়।


22
আমার সি কোডটি সি ++ এর সাথে "সামঞ্জস্যপূর্ণ" হলে পৃথিবীতে কেন আমি যত্ন করব? আমি পরোয়া করি না যদি এটা Perl বা জাভা বা আইফেল বা সঙ্গে সামঞ্জস্যপূর্ণ হয় ...
স্টিফেন ক্যানন

4
যদি আপনি গ্যারান্টি দিচ্ছেন যে কেউ আপনার লাইনের সি কোডটি দেখে যাচ্ছে না, আরে আমি এটি একটি সি ++ সংকলক দিয়ে সংকলন করতে যাচ্ছি কারণ এটি কাজ করা উচিত!
স্টিভেন লু

3
এ কারণেই বেশিরভাগ সি কোডকে তুচ্ছভাবে সি ++ সামঞ্জস্য করা যায়।
কৌতূহলী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.