উবুন্টু 12.04-তে জিসিসির সাথে সংকলন করতে পারবেন না


9

আমি আমার উবুন্টু এবং উইন্ডোজ মেশিনে জিসিসি এবং ভিসি 9 দিয়ে নীচের সি প্রোগ্রামটি সংকলন এবং চালনার চেষ্টা করছি। তবে, আমি নীচে সমস্যার মুখোমুখি হয়েছি:

উবুন্টু মেশিনে:

জিসিসি জরিমানা সংকলন করে, তবে রান করার সময় আমাকে এই প্রম্পটটি দেখানো হয়:

Segmentation Fault (Core Dump).

উইন্ডোজ মেশিনে:

ভিসি 9 সংকলন এবং জরিমানা চালায়। জিসিসি জরিমানা সংকলন করে, তবে প্রোগ্রামটি চালিত হওয়ার পরে প্রক্রিয়াটি সমাপ্ত হয়।

এখানে আপনার বিশেষজ্ঞের সহায়তা দরকার। আমার কোডটি এখানে:

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

int calc_slope(int input1,int input2)
{
    int sum=0;
    int start=input1;
    int end=input2;
    int curr=start;

    //some validation:
    if (input1>input2)
        return -1;


    while(curr<=end)
    {
        if (curr>100)
        {
            char *s="";
            int length;
            int left;
            int right;
            int cent;

            sprintf(s,"%d",curr);
            length=strlen(s);
            s++;
            do
            {
                //printf("curr=%d char=%c pointer=%d length=%d \n",curr,*s,s,length);
                left = *(s-1) - '0';
                cent = *s - '0';
                right = *(s+1) - '0';
                //printf("curr=%d l=%d c=%d r=%d\n",curr,left,cent,right);
                if ( (cent>left && cent>right) || (cent<left && cent<right) )
                {
                    sum+=1; //we have either a maxima or a minima.
                }

                s++;
            } while (*(s+1)!='\0');
        }
        curr++;
    }

    return sum;
}

int main()
{
    printf("%d",calc_slope(1,150));
    return 0;
}

হালনাগাদ:

ক্রেডিট এলিয়াকে কেবল ত্রুটিটি সনাক্ত করতে সাহায্য করার জন্য নয়, আমাকে gdbএবং এটির ব্যাক-ট্রেসিং সরঞ্জাম ( bt) উপস্থাপন করিয়েছে যা একটি সিসি সংকলিত প্রোগ্রামটি ডিবাগ করার জন্য খুব সহায়ক। পরিবর্তিত সংস্করণটি এখানে, আমি কিছু পরীক্ষা এবং ত্রুটির পরে কাজ করেছি:

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

int calc_slope(int input1,int input2)
{
    int sum=0;
    int start=input1;
    int end=input2;
    int curr=start;

    //some validation:
    if (input1>input2)
        return -1;


    while(curr<=end)
    {
        if (curr>100)
        {
            int size=10;
            char *s=(char*)malloc((size+1) * sizeof(char));
            int left;
            int right;
            int cent;

            sprintf(s,"%d",curr);
            s++;
            do
            {
                left = *(s-1) - '0';
                cent = *s - '0';
                right = *(s+1) - '0';
                if ( (cent>left && cent>right) || (cent<left && cent<right) )
                {
                    sum+=1; //we have either a maxima or a minima.
                }

                s++;
            } while (*(s+1)!='\0');
        }
        curr++;
    }

    return sum;
}

int main()
{
    printf("%d",calc_slope(1,150));
    return 0;
}

3
আমি মনে করি এটি কোনও সংকলনের সমস্যা নয়, বরং রানটাইম সমস্যা। আপনি স্ট্যাকওভারফ্লো থেকে আরও সহায়তা পাবেন ।
ওসকামায়

আপনি এই সত্যিই নিশ্চিত রান VC9 সঙ্গে কম্পাইল হওয়ার পর ভালো আছেন তো?
এলিয়াহ কাগন

হ্যাঁ, 100% তবে জিসিসি দিয়ে নয়।
প্রহ্লাদ ইয়েরি

পছন্দ করুন আমি আমার উত্তরে এর কারণ ব্যাখ্যা করেছি । (এটির অর্থ হ'ল আমাদের সম্ভবত এই প্রশ্নটি অন-টপকে বিবেচনা করা উচিত, যেহেতু এটি উবুন্টু * - স্পেসিফিক * আচরণ সম্পর্কিত। উইন্ডোজে জিসিসি তুলনামূলক আচরণ প্রদর্শন করে তবে কোনও ত্রুটি বার্তা নেই এবং সেখানে ঠিক কী ঘটছে তা জানতে অসুবিধা হয় - এছাড়াও, কখন উবুন্টু এবং মাইক্রোসফ্ট ভিজ্যুয়াল সি ++ এর উপর জিসিসি ভিন্নভাবে কাজ করে, আমি মনে করি উবুন্টুতে জিসিসি কেন এটির মতো কাজ করে তা জিজ্ঞাসা করার জন্য জিজ্ঞাসা করা উবুন্টু একটি যুক্তিসঙ্গত জায়গা that এই কথাটির সাথে, কীভাবে এটি করা যায় সে সম্পর্কে আরও প্রশ্ন স্ট্যাক ওভারফ্লোতে অন্তর্ভুক্ত belong)
এলিয়াহ কাগন

সিতে একটি স্ট্রিং আক্ষরিক পরিবর্তন অনির্ধারিত আচরণ। দয়া করে মনে রাখবেন
jn1kk

উত্তর:


15

একটি বিভাগ যখন এর জন্য বরাদ্দ করা হয়েছে তার বাইরে মেমোরি অ্যাক্সেস করার চেষ্টা করে তখন একটি সেগমেন্টেশন ত্রুটি ঘটে।

এই ক্ষেত্রে, অভিজ্ঞ সি প্রোগ্রামার দেখতে পাবে যে লাইনে ফোন করা হয়েছে সেখানে সমস্যা হচ্ছে sprintf। তবে যদি আপনি বলতে না পারেন যে আপনার বিভাগের ত্রুটিটি কোথায় ঘটছে বা যদি আপনি কোডটি পড়ে এটি অনুধাবন করার চেষ্টা করতে চান না তবে আপনি ডিবাগ চিহ্ন সহ আপনার প্রোগ্রামটি তৈরি করতে পারেন (সহ gcc, -gপতাকাটি এটি করে ) এবং তারপরে এটি একটি ডিবাগারের মাধ্যমে চালিত করুন।

আমি আপনার উত্স কোডটি অনুলিপি করে এটিকে আমার নামের একটি ফাইলে আটকালাম slope.c। তারপরে আমি এটি এটির মতো তৈরি করেছি:

gcc -Wall -g -o slope slope.c

(এটি -Wallisচ্ছিক। এটি আরও পরিস্থিতিতে সতর্কবার্তা উত্পন্ন করার জন্য to এটি কী ভুল হতে পারে তা নির্ধারণেও সহায়তা করতে পারে))

তারপরে আমি প্রোগ্রামটি শুরু করার জন্য gdbপ্রথমে ছুটে গিয়ে ডিবাগারে প্রোগ্রামটি চালিত করি এবং তারপরে একবার ডিবাগারে, ডিবাগারকে কমান্ড দিয়ে:gdb ./slopegdbrun

ek@Kip:~/source$ gdb ./slope
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/ek/source/slope...done.
(gdb) run
Starting program: /home/ek/source/slope 
warning: Cannot call inferior functions, you have broken Linux kernel i386 NX (non-executable pages) support!

Program received signal SIGSEGV, Segmentation fault.
0x001a64cc in _IO_default_xsputn () from /lib/i386-linux-gnu/libc.so.6

(আমার you have broken Linux kernel i386 NX... supportবার্তা সম্পর্কে উদ্বিগ্ন হবেন না ; এটি gdbএই প্রোগ্রামটি ডিবাগ করার জন্য কার্যকরভাবে ব্যবহার হতে বাধা দেয় না ))

এই তথ্যটি অত্যন্ত ক্রিপ্টিক ... এবং যদি আপনার কাছে ডিবিগ প্রতীকগুলি libc এর জন্য ইনস্টল করা না থাকে তবে আপনি আরও একটি ক্রিপ্টিক বার্তা পাবেন যা প্রতীকী ফাংশন নামের পরিবর্তে একটি হেক্সাডেসিমাল ঠিকানা রয়েছে _IO_default_xsputn। ভাগ্যক্রমে, এতে কিছু যায় আসে না, কারণ আমরা যা জানতে চাই তা হ'ল আপনার প্রোগ্রামে সমস্যাটি কোথায় ঘটছে।

সুতরাং, সমাধানটি পিছনের দিকে তাকাতে হবে, কোনও সিস্টেম লাইব্রেরিতে যে নির্দিষ্ট ফাংশন কলটি SIGSEGVসংকেত অবশেষে ট্রিগার হয়েছিল সেখানে কী ফাংশন কলগুলি ঘটেছিল তা দেখার জন্য ।

gdb(এবং যে কোনও ডিবাগার) এর মধ্যে এই বৈশিষ্ট্যটি অন্তর্নির্মিত রয়েছে: একে স্ট্যাক ট্রেস বা ব্যাকট্র্যাস বলা হয় । আমি btএকটি ব্যাকট্রেস উত্পন্ন করতে ডিবাগার কমান্ডটি ব্যবহার করি gdb:

(gdb) bt
#0  0x001a64cc in _IO_default_xsputn () from /lib/i386-linux-gnu/libc.so.6
#1  0x00178e04 in vfprintf () from /lib/i386-linux-gnu/libc.so.6
#2  0x0019b234 in vsprintf () from /lib/i386-linux-gnu/libc.so.6
#3  0x0017ff7b in sprintf () from /lib/i386-linux-gnu/libc.so.6
#4  0x080484cc in calc_slope (input1=1, input2=150) at slope.c:26
#5  0x08048578 in main () at slope.c:52
(gdb)

আপনি দেখতে পাচ্ছেন যে আপনার mainফাংশনটি ফাংশনটিকে কল করে calc_slope(যা আপনি ইচ্ছা করেছেন) এবং তারপরে calc_slopeকলগুলি sprintf(যা এই সিস্টেমে) অন্যান্য কয়েকটি সম্পর্কিত লাইব্রেরির ফাংশনগুলিতে কল সহ প্রয়োগ করা হয়েছে।

আপনি যা সম্পর্কে সাধারণত আগ্রহী তা হ'ল আপনার প্রোগ্রামের ফাংশন কল যা আপনার প্রোগ্রামের বাইরে কোনও ফাংশনকে কল করে । আপনি যে লাইব্রেরি / লাইব্রেরিগুলিতে নিজেরাই ব্যবহার করছেন সেগুলির মধ্যে কোনও বাগ না থাকলে (এই ক্ষেত্রে, libcলাইব্রেরি ফাইল দ্বারা সরবরাহিত স্ট্যান্ডার্ড সি লাইব্রেরি libc.so.6), ক্র্যাশ হওয়ার কারণটি আপনার প্রোগ্রামে রয়েছে এবং প্রায়শই এটির কাছাকাছি বা কাছাকাছি থাকবে আপনার প্রোগ্রামে শেষ কল

এই ক্ষেত্রে, এটি:

#4  0x080484cc in calc_slope (input1=1, input2=150) at slope.c:26

আপনার প্রোগ্রাম কল যেখানে সেখানে sprintf। আমরা এটি জানি কারণ sprintfপরবর্তী পদক্ষেপ। তবে এটি উল্লেখ না করেও আপনি এটি জানেন কারণ ২ line লাইনে এটিই ঘটে এবং এটি বলে:

... at slope.c:26

আপনার প্রোগ্রামে 26 লাইনে রয়েছে:

            sprintf(s,"%d",curr);

(আপনার সর্বদা এমন একটি পাঠ্য সম্পাদক ব্যবহার করা উচিত যা কমপক্ষে আপনি বর্তমানে যে লাইনে রয়েছেন তার জন্য স্বয়ংক্রিয়ভাবে লাইন নম্বরগুলি প্রদর্শন করে।

ডেনিস কার্সেমেকারের উত্তরে যেমন আলোচনা হয়েছে , তেমনিs এক বাইট অ্যারে। (শূন্য নয়, কারণ যে মানটি আপনি এটি নির্ধারণ করেছেন, ""এটি একটি বাইট দীর্ঘ, অর্থাৎ এটি সমান { '\0' }, একইভাবে "Hello, world!\n"সমান { 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', '\0' }))

সুতরাং, কেন এটি এখনও কিছু প্ল্যাটফর্মে কাজ করতে পারে (এবং উইন্ডোজের জন্য ভিসি 9 দিয়ে সংকলন করার সময় দৃশ্যত তা করতে পারে)?

লোকেরা প্রায়শই বলে থাকে যে আপনি যখন মেমরি বরাদ্দ করেন এবং তার বাইরে স্মৃতি অ্যাক্সেস করার চেষ্টা করেন, এটি একটি ত্রুটি তৈরি করে। তবে এটি সত্য নয়। সি এবং সি ++ প্রযুক্তিগত মান অনুসারে, এটি সত্যিই যা উত্পন্ন করে তা হ'ল সংজ্ঞায়িত আচরণ।

অন্য কথায়, কিছু ঘটতে পারে!

তবুও কিছু জিনিস অন্যদের চেয়ে বেশি হয়। কেন এটি হ'ল স্ট্যাকের একটি ছোট অ্যারে, কিছু প্রয়োগে, স্ট্যাকের উপরে আরও বড় অ্যারের মতো কাজ করতে প্রদর্শিত হবে?

এটি স্ট্যাক বরাদ্দ কীভাবে প্রয়োগ করা হয় তার নীচে আসে, যা প্ল্যাটফর্ম থেকে প্ল্যাটফর্মের পরিবর্তে পৃথক হওয়ার অনুমতি দেওয়া হয়। আপনার এক্সিকিউটেবল তার স্ট্যাকটিতে আরও একবারে মেমরি বরাদ্দ করতে পারে যা আসলে কোনও এক সময় ব্যবহারের উদ্দেশ্যে করা হয়। কখনও কখনও এটি আপনাকে মেমোরি অবস্থানগুলিতে লেখার অনুমতি দিতে পারে যা আপনি আপনার কোডটিতে স্পষ্টভাবে দাবি করেননি । ভিসি 9-এ আপনি যখন আপনার প্রোগ্রামটি তৈরি করেন তখন খুব সম্ভবত এটি ঘটছে।

তবে, ভিসি 9 তেও আপনার এই আচরণের উপর নির্ভর করা উচিত নয়। এটি বিভিন্ন উইন্ডোজ সিস্টেমে থাকা লাইব্রেরির বিভিন্ন সংস্করণের উপর নির্ভর করে। তবে আরও সম্ভবত সমস্যাটি হ'ল অতিরিক্ত স্ট্যাক স্পেসটি বরাদ্দ করা হয় এই উদ্দেশ্য নিয়ে যে এটি আসলে ব্যবহৃত হবে, এবং তাই এটি বাস্তবে ব্যবহৃত হতে পারে।তারপরে আপনি "অপরিজ্ঞাত আচরণের" পুরো দুঃস্বপ্নটি অনুভব করেন যেখানে এই ক্ষেত্রে একাধিক ভেরিয়েবল একই স্থানে সঞ্চিত হতে পারে, যেখানে একজনকে লেখা অন্যটিকে ওভাররাইট করে ... তবে সর্বদা নয়, কারণ কখনও কখনও ভেরিয়েবলগুলিকে লেখেন নিবন্ধগুলিতে ক্যাশে হয় এবং তাত্ক্ষণিকভাবে সম্পাদন করা হয় না (বা ভেরিয়েবলগুলি পড়তে ক্যাশে করা যেতে পারে, বা কোনও ভেরিয়েবলটি আগের মতো একইরূপে ধরে নেওয়া যেতে পারে কারণ এটি বরাদ্দ করা মেমরিটি কম্পাইলার দ্বারা জানা যায় যে এটি লিখিত হয়নি) পরিবর্তনশীল নিজেই)।

এবং এটি ভিসি 9 দিয়ে নির্মিত যখন প্রোগ্রামটি কেন কাজ করেছিল তার অন্যান্য সম্ভাবনার সম্ভাবনা আমার কাছে নিয়ে আসে। এটি সম্ভব এবং কিছুটা সম্ভবত, ওয়ান-বাইট অ্যারের পরে স্থানটি ব্যবহার করার জন্য কিছু অ্যারে বা অন্যান্য ভেরিয়েবল আসলে আপনার প্রোগ্রাম দ্বারা বরাদ্দ করা হয়েছিল (যার মধ্যে আপনার প্রোগ্রামটি ব্যবহার করা একটি লাইব্রেরি দ্বারা বরাদ্দ থাকা অন্তর্ভুক্ত থাকতে পারে) s। সুতরাং, sআর একটি বাইটের চেয়ে বেশি অ্যারে হিসাবে চিকিত্সা করার ফলে সেই / সেইগুলি পরিবর্তনশীল / অ্যারেগুলির সামগ্রী অ্যাক্সেস করার প্রভাব পড়বে, যা খারাপও হতে পারে।

উপসংহারে, যখন আপনার মতো ভুল হয় তখন "বিভাগীয় ত্রুটি" বা "সাধারণ সুরক্ষা ত্রুটি" এর মতো ত্রুটি পাওয়া ভাগ্যবান । তুমি কখন না যে আছে, তবে আপনি নট আউট খুঁজে পেতে পারেন না হওয়া পর্যন্ত এটা খুব দেরি হয়ে যে আপনার প্রোগ্রাম আছে অনির্ধারিত আচরণ।


1
এই ধরনের সুস্পষ্ট ব্যাখ্যা জন্য ধন্যবাদ। এটা ঠিক আমার যা প্রয়োজন তা .. !!
প্রহ্লাদ ইয়েরি

9

হ্যালো বাফার ওভারফ্লো!

char *s="";
sprintf(s,"%d",curr);
length=strlen(s);

আপনি স্ট্যাকের স্ট্রিংয়ের জন্য একটি বাইট বরাদ্দ করেন এবং তারপরে এটিতে একাধিক বাইট লেখার জন্য এগিয়ে যান। এবং এটিকে শীর্ষে রাখতে, আপনি সেই অ্যারের শেষের বাইরে পড়েছেন। দয়া করে একটি সি ম্যানুয়াল এবং বিশেষত স্ট্রিংগুলি এবং তাদের জন্য মেমরি বরাদ্দের বিভাগটি পড়ুন।


হ্যাঁ আমি পরে এটি সম্পর্কে জানতে পারি। তবে আমি যখন এটি লিখেছিলাম, ভিসি 9 সংকলকটি কেবল অনুমতিই দেয়নি, তবে ফলাফলগুলি আমাকে সঠিকভাবে প্রদর্শন করেছে। আমি স্ট্রেন (গুলি) প্রিন্ট-এডি করেছি এবং এটি আমাকে দেখিয়েছে 4 টি, না !!
প্রহ্লাদ ইয়েরি

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

আমি করতে পারি, তবে প্রোগ্রামিং পরামর্শ দেওয়ার জন্য আপনার সত্যিকারের স্ট্যাক ওভারফ্লোতে যাওয়া উচিত, কারণ এটি এখানে বেশ অফটোপিক।
ডেনিস কার্সেমেকার

1
@ ডেনিসকর্সেমেকার এখানে মূল প্রশ্নটি বিষয়বস্তু নাও থাকতে পারে কারণ এটিতে উবুন্টু এবং অন্য প্ল্যাটফর্মের মধ্যে পৃথক পৃথক আচরণের বিষয়টি স্পষ্টত জড়িত (এবং আমি আমার উত্তরে এর সর্বাধিক কারণ ব্যাখ্যা করেছি )। আমি সম্মত হই যে সিতে স্ট্রিংগুলি কীভাবে সঠিকভাবে বরাদ্দ করা যায় সে সম্পর্কে প্রশ্নগুলি এখানে স্ট্যাক ওভারফ্লোতে অন্তর্ভুক্ত।
এলিয়াহ কাগন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.