মেমোমোভ এবং মেমকপির মধ্যে পার্থক্য কী?


উত্তর:


162

এর সাথে memcpy, গন্তব্যটি উত্সটি মোটেই ওভারল্যাপ করতে পারে না। memmoveএটা দিয়ে । এর অর্থ এটি memmoveতুলনামূলকভাবে সামান্য ধীর হতে পারে memcpyকারণ এটি একই অনুমানগুলি তৈরি করতে পারে না।

উদাহরণস্বরূপ, memcpyসর্বদা কম থেকে উচ্চে ঠিকানাগুলি অনুলিপি করতে পারে। যদি উত্সটির পরে গন্তব্যটি ওভারল্যাপ হয়ে যায়, এর অর্থ কয়েকটি অনুলিপি অনুলিপি করার আগেই মুছে ফেলা হবে। memmoveএটিকে সনাক্ত করে অন্য দিকে - উচ্চ থেকে নিম্নে - অনুলিপি করবে। তবে এটি পরীক্ষা করে অন্য কোনও (সম্ভবত কম দক্ষ) অ্যালগরিদমে স্যুইচ করতে সময় লাগে।


1
মেমকিপি ব্যবহার করার সময়, আমি কীভাবে গ্যারান্টি দিতে পারি যে এসসিআর এবং ডেস্ট ঠিকানাগুলি ওভারল্যাপ হয় না? আমার ব্যক্তিগতভাবে নিশ্চিত হওয়া উচিত যে এসসিআর এবং গন্তব্যগুলি ওভারল্যাপে না চলে?
অ্যালকোট

6
@ অ্যালকোট, মেমপি ব্যবহার করবেন না যদি আপনি না জানেন যে তারা ওভারল্যাপ করে না - পরিবর্তে মেমমোভ ব্যবহার করুন। যখন কোনও ওভারল্যাপ নেই, মেমোমোভ এবং মেমকিপি সমতুল্য (যদিও মেমকি খুব, খুব, খুব সামান্য দ্রুত হতে পারে)।
বিডনলান

আপনি যদি দীর্ঘ অ্যারে নিয়ে কাজ করে থাকেন এবং আপনার অনুলিপি প্রক্রিয়াটি সুরক্ষা রাখতে চান তবে আপনি 'সীমাবদ্ধ' কীওয়ার্ডটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, যদি আপনি পদ্ধতিটি প্যারামিটারগুলির ইনপুট এবং আউটপুট অ্যারে হিসাবে গ্রহণ করে এবং আপনাকে অবশ্যই যাচাই করতে হবে যে ব্যবহারকারী একই ঠিকানাটি ইনপুট এবং আউটপুট হিসাবে পাস করবে না। এখানে পড়ুন stackoverflow.com/questions/776283/...
DanielHsH

10
@ ড্যানিয়েলএইচএসএইচ 'সীমাবদ্ধ' এমন একটি প্রতিশ্রুতি যা আপনি সংকলক করেছেন; এটি সংকলক দ্বারা প্রয়োগ করা হয় না । যদি আপনি আপনার যুক্তিগুলিতে 'সীমাবদ্ধ' রেখে দেন এবং বাস্তবে ওভারল্যাপ করে থাকেন (বা আরও সাধারণভাবে, একাধিক স্থান থেকে প্রাপ্ত পয়েন্টার থেকে সীমাবদ্ধ ডেটা অ্যাক্সেস করে), প্রোগ্রামটির আচরণটি সংজ্ঞায়িত হয়, অদ্ভুত বাগগুলি ঘটবে এবং সংকলক এটি সম্পর্কে সাধারণত আপনাকে সতর্ক করবে না।
বিডনলান

@ বিডনলান এটি কেবল সংকলকের প্রতিশ্রুতি নয়, এটি আপনার কলারের প্রয়োজন। এটি এমন একটি প্রয়োজনীয়তা যা প্রয়োগ করা হয় না তবে আপনি যদি কোনও প্রয়োজনীয়তা লঙ্ঘন করেন তবে অপ্রত্যাশিত ফলাফল পেলে আপনি অভিযোগ করতে পারবেন না। কোনও প্রয়োজনের লঙ্ঘন করা অপরিজ্ঞাত আচরণ i = i++ + 1যেমন ঠিক তেমনি সংজ্ঞায়িত; সংকলক আপনাকে ঠিক সেই কোডটি লিখতে নিষেধ করে না তবে সেই নির্দেশের ফলাফলটি যে কোনও কিছুই হতে পারে এবং বিভিন্ন সংকলক বা সিপিইউগুলি এখানে বিভিন্ন মান দেখায়।
মক্কি

33

memmoveওভারল্যাপিং মেমরি পরিচালনা করতে পারে, memcpyপারে না।

বিবেচনা

char[] str = "foo-bar";
memcpy(&str[3],&str[4],4); //might blow up

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

memmove(&str[3],&str[4],4); //fine

5
কেন প্রথম উড়ে যাবে?

4
@ultraman: কারণ এটি নিম্ন স্তরের এসেম্বলি ব্যবহার করে কার্যকর করা যেতে পারে যার জন্য মেমরিটি ওভারল্যাপ হয় না requires যদি এটি করে তবে আপনি উদাহরণস্বরূপ প্রসেসরের একটি সংকেত বা হার্ডওয়্যার ব্যতিক্রম উত্পন্ন করতে পারবেন যা অ্যাপ্লিকেশনটি বাতিল করে দেয়। ডকুমেন্টেশনটি উল্লেখ করে যে এটি শর্তটি পরিচালনা করে না, তবে মানকটি নির্দিষ্ট করে না যে যখন এই শর্তগুলি শূন্য হয় তখন এটি কী হবে (এটি অপরিবর্তিত আচরণ হিসাবে পরিচিত)। অপরিজ্ঞাত আচরণ কিছু করতে পারে।
মার্টিন ইয়র্ক

জিসিসি ৪.৮.২ সহ, এমনকি মেমকিও ওভারল্যাপিং উত্স এবং গন্তব্য পয়েন্টার গ্রহণ করে এবং সূক্ষ্মভাবে কাজ করে।
গিকিজে

4
পছন্দ করুন তবে যেহেতু মেমকিটি এটি সমর্থন না করার জন্য নথিভুক্ত করা হয়েছে, তাই আপনার সেই বাস্তবায়ন নির্দিষ্ট আচরণের উপর নির্ভর করা উচিত নয়, এ কারণেই মেমমোভ () বিদ্যমান। এটি জিসিসির অন্য সংস্করণে আলাদা হতে পারে। এটি আলাদা হতে পারে যদি গিসিসি গ্লোবিকে মেমপিকে () এ কল করার পরিবর্তে মেমপিকে ইনলাইন করে, এটি গ্লিবকের আরও পুরানো বা নতুন সংস্করণে আলাদা হতে পারে।
নম্বর

অনুশীলন থেকে, মনে হয় মেমকি এবং মেমোমও একই কাজ করেছে। এরকম গভীর অপরিবর্তিত আচরণ।
জীবন

22

থেকে আমার মনে মানুষ পাতা।

মেমকিপি () ফাংশন এন বাইটগুলি মেমরি অঞ্চল src থেকে মেমরি অঞ্চল গন্তব্যে অনুলিপি করে। মেমরি অঞ্চলগুলি ওভারল্যাপ করা উচিত নয়। মেমোরি অঞ্চলগুলি ওভারল্যাপ করে থাকলে মেমমোভ (3) ব্যবহার করুন ।


12

মধ্যে মূল পার্থক্য memmove()এবং memcpy()যে হয় memmove()একটি বাফার অস্থায়ী মেমরির - - ব্যবহার করা হয়, তাই ওভারল্যাপিং হওয়ার কোনো সম্ভাবনা নেই। অন্যদিকে, উত্স দ্বারা নির্দেশিত অবস্থান থেকে গন্তব্য দ্বারা নির্দেশিত অবস্থানের memcpy()সরাসরি অবস্থান থেকে ডেটা অনুলিপি করে । ( http://www.cplsplus.com/references/cstring/memcpy/ )

নিম্নলিখিত উদাহরণগুলি বিবেচনা করুন:

  1. #include <stdio.h>
    #include <string.h>
    
    int main (void)
    {
        char string [] = "stackoverflow";
        char *first, *second;
        first = string;
        second = string;
    
        puts(string);
        memcpy(first+5, first, 5);
        puts(first);
        memmove(second+5, second, 5);
        puts(second);
        return 0;
    }
    

    যেমনটি আপনি প্রত্যাশা করেছিলেন, এটি মুদ্রণ করবে:

    stackoverflow
    stackstacklow
    stackstacklow
    
  2. তবে এই উদাহরণে ফলাফলগুলি একই রকম হবে না:

    #include <stdio.h>
    #include <string.h>
    
    int main (void)
    {
        char string [] = "stackoverflow";
        char *third, *fourth;
        third = string;
        fourth = string;
    
        puts(string);
        memcpy(third+5, third, 7);
        puts(third);
        memmove(fourth+5, fourth, 7);
        puts(fourth);
        return 0;
    }
    

    আউটপুট:

    stackoverflow
    stackstackovw
    stackstackstw
    

এটি কারণ "মেমকিপি ()" নিম্নলিখিতগুলি করে:

1.  stackoverflow
2.  stacksverflow
3.  stacksterflow
4.  stackstarflow
5.  stackstacflow
6.  stackstacklow
7.  stackstacksow
8.  stackstackstw

2
তবে, মনে হচ্ছে আপনি উল্লিখিত আউটপুটটি বিপরীত হয়েছে !!
কুমার

1
আমি যখন একই প্রোগ্রামটি চালনা করি তখন আমি নিম্নলিখিত ফলাফলটি পাই: স্ট্যাকওভারফ্লো স্ট্যাকস্ট্যাকস্টউ স্ট্যাকস্ট্যাকস্টউ // মানে মেমকি এবং মেমমোভের মধ্যে আউটপুটে কোনও পার্থক্য নেই
কুমার

4
"এটি" মেমমোভ () "এ, একটি বাফার - একটি অস্থায়ী স্মৃতি - ব্যবহৃত হয়;" সত্য না. এটি "যেন" বলেছে তাই এটি ঠিক এমন আচরণ করতে হবে, এমন নয় যে এটি সেভাবে হতে হবে। বেশিরভাগ স্মৃতিচারণ বাস্তবায়ন হিসাবে প্রকৃতপক্ষে প্রাসঙ্গিকভাবে কেবল একটি এক্সওআর-অদলবদল করে।

2
আমি মনে করি না memmove()বাফার ব্যবহারের বাস্তবায়ন প্রয়োজন। এটি জায়গায় স্থানান্তরিত করার পুরোপুরি অধিকারী (যতক্ষণ প্রতিটি পঠন একই ঠিকানায় কোনও লেখার আগে শেষ হয়)।
টবি স্পিড

12

ধরে নিই যে আপনার উভয়কেই প্রয়োগ করতে হবে, বাস্তবায়নটি এরকম দেখতে পারা যায়:

void memmove ( void * dst, const void * src, size_t count ) {
    if ((uintptr_t)src < (uintptr_t)dst) {
        // Copy from back to front

    } else if ((uintptr_t)dst < (uintptr_t)src) {
        // Copy from front to back
    }
}

void mempy ( void * dst, const void * src, size_t count ) {
    if ((uintptr_t)src != (uintptr_t)dst) {
        // Copy in any way you want
    }
}

এবং এটি খুব ভাল পার্থক্য ব্যাখ্যা করা উচিত। memmoveসর্বদা এই জাতীয়ভাবে অনুলিপি করুন যে এটি srcও নিরাপদ থাকলেও dstওভারল্যাপ হয়, memcpyযখন ব্যবহারের সময় ডকুমেন্টেশন যেমন বলে ঠিক তেমন যত্ন নেয় না memcpy, দুটি মেমরি অঞ্চল অবশ্যই ওভারল্যাপ করা উচিত নয়

উদাহরণস্বরূপ যদি memcpyঅনুলিপিগুলি "সামনে থেকে পিছনে" থাকে এবং মেমরি ব্লকগুলি এটির মতো করে থাকে

[---- src ----]
            [---- dst ---]

এর প্রথম বাইট অনুলিপি করে অনুলিপি srcকরার dstআগে এর শেষ বাইটগুলির সামগ্রীটি ইতিমধ্যে নষ্ট করে দেয় src। কেবলমাত্র "পিছনে সামনের দিকে" অনুলিপি করা সঠিক ফলাফলের দিকে নিয়ে যাবে।

এখন অদলবদল srcএবং dst:

[---- dst ----]
            [---- src ---]

srcসেক্ষেত্রে প্রথম বাইটটি অনুলিপি করার সময় "সামনে থেকে পিছনে" অনুলিপি করা নিরাপদ যেমন "পিছনে সামনের দিকে" অনুলিপি করা হবে এর আগেই এর সম্মুখের কাছে ধ্বংস হয়ে যাবে ।

আপনি লক্ষ করেছেন যে memmoveউপরের বাস্তবায়ন এমনকি যদি তারা ওভারল্যাপ করে তবে এটি পরীক্ষা করে না, এটি কেবল তাদের আপেক্ষিক অবস্থানগুলি পরীক্ষা করে, তবে এটিই অনুলিপিটি নিরাপদ করে তুলবে। যেহেতু memcpyসাধারণত কোনও সিস্টেমে মেমরি অনুলিপি করার জন্য দ্রুততম উপায় ব্যবহার করে, memmoveসাধারণত তা প্রয়োগ করা হয়:

void memmove ( void * dst, const void * src, size_t count ) {
    if ((uintptr_t)src < (uintptr_t)dst
        && (uintptr_t)src + count > (uintptr_t)dst
    ) {
        // Copy from back to front

    } else if ((uintptr_t)dst < (uintptr_t)src
        && (uintptr_t)dst + count > (uintptr_t)src
    ) {
        // Copy from front to back

    } else {
        // They don't overlap for sure
        memcpy(dst, src, count);
    }
}

কখনও কখনও, memcpy"সর্বদা থেকে পিছনে" বা "পিছনে সামনের দিকে" অনুলিপি করা থাকলে , ওভারল্যাপিংয়ের একটিতে memmoveব্যবহার memcpyকরা memcpyযেতে পারে তবে ডেটা কীভাবে সংযুক্ত করা হয় এবং / অথবা কতটা ডেটা থাকতে হবে তার উপর নির্ভর করে অন্যভাবে অনুলিপিও করতে পারে অনুলিপি করা হয়েছে, সুতরাং এমনকি যদি আপনি memcpyনিজের সিস্টেমে অনুলিপিগুলি পরীক্ষা করে থাকেন তবে আপনি সর্বদা সঠিক হওয়ার জন্য পরীক্ষার ফলাফলের উপর নির্ভর করতে পারবেন না।

কোনটি কল করতে হবে তা সিদ্ধান্ত নেওয়ার সময় এর অর্থ কী?

  1. আপনি যদি নিশ্চিতভাবে না জানেন srcএবং dstওভারল্যাপ না memmoveকরেন তবে কল করুন এটি সর্বদা সঠিক ফলাফলের দিকে পরিচালিত করবে এবং আপনার প্রয়োজনীয় অনুলিপি মামলার পক্ষে এটি যতটা দ্রুত সম্ভব তত দ্রুত।

  2. আপনি যদি নিশ্চিতভাবে জানেন srcএবং dstওভারল্যাপ memcpyনা করেন তবে কল করুন কারণ আপনি ফলাফলটির জন্য যাকে কল করেন তা বিবেচনাধীন নয়, উভয়ই সেই ক্ষেত্রে সঠিকভাবে কাজ করবে, তবে memmoveকখনই দ্রুত হবে না memcpyএবং আপনি যদি দুর্ভাগ্য হন তবে তা এমনকি হতে পারে ধীর হয়ে উঠুন, যাতে আপনি কেবল কলিং জয় করতে পারেন memcpy


+1 কারণ আপনার "এসকি আঁকাগুলি" কেন ডেটা নষ্ট না করে ওভারল্যাপিং হতে পারে না তা বোঝার জন্য দরকারী ছিল
সাইক্লার্ডোর

10

একটি ওভারল্যাপিং গন্তব্যগুলি পরিচালনা করে যা অন্যটি করে না।


6

কেবল আইএসও / আইইসি: 9899 স্ট্যান্ডার্ড থেকে এটি ভালভাবে বর্ণিত।

7.21.2.1 মেমকি ফাংশন

[...]

2 মেমকি ফাংশনটি এস 2 দ্বারা নির্দেশিত বস্তুর মধ্যে এস 1 দ্বারা নির্দেশিত বস্তু থেকে n অক্ষর অনুলিপি করে। যদি অনুলিপি করা বস্তুগুলির মধ্যে অনুলিপি হয়, তবে আচরণটি সংজ্ঞায়িত।

এবং

7.21.2.2 মেমোমোভ ফাংশন

[...]

2 মেমমোভ ফাংশনটি এস 2 দ্বারা নির্দেশিত বস্তুর মধ্যে এস 1 দ্বারা নির্দেশিত বস্তু থেকে n অক্ষর অনুলিপি করে। অনুলিপিটি সংঘটিত হয় যেমন s2 দ্বারা নির্দেশিত বস্তু থেকে এন অক্ষরগুলি প্রথমে n অক্ষরের অস্থায়ী অ্যারেতে অনুলিপি করা হয় যা s1 এবং s2 দ্বারা নির্দেশিত বস্তুগুলিকে ওভারল্যাপ করে না এবং তারপরে অস্থায়ী অ্যারে থেকে এন অক্ষরগুলি অনুলিপি করা হয় s1 দ্বারা নির্দেশিত বস্তু।

আমি সাধারণত কোনটি প্রশ্নের সাথে আকৃতি ব্যবহার করি তা নির্ভর করে যে আমার কী কার্যকারিতা প্রয়োজন on

সাধারণ পাঠে memcpy()অনুমতি দেয় না s1এবং s2অধিক্রমনের, যখন memmove()আছে।


0

প্রয়োগের দুটি সুস্পষ্ট উপায় রয়েছে mempcpy(void *dest, const void *src, size_t n)(ফেরতের মান উপেক্ষা করে):

  1. for (char *p=src, *q=dest;  n-->0;  ++p, ++q)
        *q=*p;
  2. char *p=src, *q=dest;
    while (n-->0)
        q[n]=p[n];

প্রথম প্রয়োগে, অনুলিপিটি নিম্ন থেকে উচ্চ ঠিকানাগুলিতে এবং দ্বিতীয়টিতে উচ্চ থেকে নীচে চলে যায়। যদি সীমাটি ওভারল্যাপে অনুলিপি করা হয় (যেমন ফ্রেমবফারটি স্ক্রোল করার ক্ষেত্রে যেমন হয়, উদাহরণস্বরূপ), তবে কেবল অপারেশনের এক দিক সঠিক, এবং অন্যটি সেই অবস্থানগুলি ওভাররাইট করে যা পরবর্তীতে পড়তে হবে।

একটি memmove()বাস্তবায়ন, এর সহজতম সময়ে, পরীক্ষা করা হবে dest<src(কিছু প্ল্যাটফর্ম নির্ভর উপায়ে), এবং এর যথাযথ দিকটি কার্যকর করবে memcpy()

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


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


0

মেমমোভ ওভারল্যাপিং উত্স এবং গন্তব্য অঞ্চলগুলির সাথে ডিল করতে পারে, যখন মেমকিটি পারে না। দুটির মধ্যে মেমকি অনেক বেশি দক্ষ। সুতরাং, আপনি যদি এটি করতে পারেন তবে মেমকিটি ব্যবহার করা আরও ভাল।

তথ্যসূত্র: https://www.youtube.com/watch?v=Yr1YnOVG-4g ডাঃ জেরি কেইন, (স্ট্যানফোর্ড ইন্ট্রো সিস্টেমের বক্তৃতা - 7) সময়: 36:00


এই উত্তরটি "সম্ভবত একটি স্মিজ দ্রুত" বলেছে এবং মাত্রিক পার্থক্য নির্দেশ করে পরিমাণগত ডেটা সরবরাহ করে। এই উত্তরটি দৃ one়ভাবে জানায় যে একটি "অনেক বেশি দক্ষ"। আপনি আরও দ্রুত কতটা দক্ষ খুঁজে পেয়েছেন? বিটিডাব্লু: আমি ধরে নিচ্ছি আপনার মানে memcpy()এবং না memcopy()
chux - মনিকা

মন্তব্যটি ডঃ জেরি কেইনের বক্তৃতার ভিত্তিতে করা হয়েছে। আমি আপনাকে অনুরোধ করব আপনার বক্তৃতাটি 36:00 সময় শোনার জন্য, কেবলমাত্র 2-3 মিনিটই যথেষ্ট হবে। এবং ধরার জন্য ধন্যবাদ। : ডি
এহসান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.