Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разыменование указателя с получением NullReference, реализация Кнута-Морриса-Пратта на С# 
V
    Опции темы
magesi
  Дата 8.6.2012, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 20.5.2012

Репутация: нет
Всего: -4



Привет всем!

Я пытаюсь имплементировать алгоритм Кнута-Морриса-Пратта ( далее КМП ) на C# по аналогии с реализацией на чистом Си.

Про RegEx, ручную работу памяти и прочее не рассказывать мне , пожалуйста  smile т.к. цель этого вопроса не в "правильном использовании на Шарпе чего-то",
а в понимании работы с указателями именно на Шарпе, а также работы с памятью с изучением именно этих особенностей.

Привожу код на Шарпе и Си с реализацией КМП:

C#
Код

using System;

unsafe class Program
{
    static int kmp(char[] substr, char[] str)
    {
        int i, j, N, M;

        N = str.Length;
        M = substr.Length;

        int*[] d = new int*[M * sizeof(int)];
        *d[0] = 0;

        for (i = 0, j = 0; i < M; i++)
        {
            while (j > 0 && substr[j] != substr[i])
            {
                *d[j] = i - 1;
            }

            if (substr[j] == substr[i])
            {
                j++;
                *d[i] = j;
            }
        }

        for (i = 0, j = 0; i < N; i++)
        {
            while (j > 0 && substr[j] != str[i])
            {
                *d[j] = i - 1;
            }

            if (substr[j] == str[i])
            {
                j++;
            }

            if (j == M)
            {
                d = null;
                GC.Collect();
                return i - j + 1;
            }
        }

        d = null;
        GC.Collect();

        return -1;
    }

    static void Main()
    {
        char[] substr = "World".ToCharArray(),
            str = "Hello World!\r\n".ToCharArray();

        int pos = kmp(substr, str);
    }
}


C++
Код

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

int kmp(char substr[], char str[])
{
    int i, j, N, M;

    N = strlen(str);
    M = strlen(substr);

    int *d = (int*)malloc(M * sizeof(int));
    d[0] = 0;

    for(i = 0, j = 0; i < M; i++)
    {
        while(j > 0 && substr[j] != substr[i])
        {
            d[j] = i - 1;
        }

        if(substr[j] == substr[i])
        {
            j++;
            d[i] = j;
        }
    }

    for(i = 0, j = 0; i < N; i++)
    {
        while(j > 0 && substr[j] != str[i])
        {
            d[j] = i - 1;
        }

        if(substr[j] == str[i])
        {
            j++;
        }

        if(j == M)
        {
            free(d);
            return i- j + 1;
        }
    }

    free(d);

    return -1;
}

int main(void)
{
    char substr[] = "World",
        str[] = "Hello World!\r\n";

    int pos = kmp(substr, str);

    return 0;
}


На Си все идеально работает и без проблем.

На шарпе я получаю: NullReferenceException was handled.

В строке:
Код

int*[] d = new int*[M * sizeof(int)];
*d[0] = 0; //ошибка


С английского NullReferenceException я перевел, как исключение нулевой ссылки.

Почитал в msdn про это:
http://msdn.microsoft.com/ru-ru/library/sy...eexception.aspx

Исключение, возникающее при попытке разыменования указателя NULL на объект.

Только не пойму... Разыменовал указатель *d, но почему NULL на объект?

Я же выделил память оператором new[] для указателя *d на массив int. Память выделена, то почему NULL?

Потом, чтобы принудительно чистить на C#, насколько я помню, нужно вызвать метод Dispose() ( его нет для *d ), приравнять к null и вызвать GC.Collect() правильно?

PS
Хотя, понимаю свою ошибку... В Шарпе int*[] - я создаю массив указателей, чьи члены CLR прировняет к 0.

Это сообщение отредактировал(а) magesi - 8.6.2012, 12:20
PM MAIL   Вверх
erm0l0v
Дата 8.6.2012, 10:30 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Правильнее было бы работать с указателями через Marshal. Но правда есть один минус код станет менее читабельным, но тогда не будет необходимости в использовании ключевого слова unsafe

Для работы ключевого слова unsafe необходимо указать компилятору что в проекте содержится неуправляемый код. Properties->Build->Allow unsafe code

Код

int*[] d = new int*[M * sizeof(int)];


по моему M * sizeof(int) это лишнее, можно просто M.

И мне не совсем понятно зачем в этой задаче использовать указатели?

Dispose() - это просто функция, которая используется для освобождения ресурсов. Она автоматически вызывается в конце блока using что повышает читабельность кода.

По поводу GC.Collect() я точно не уверен, но по моему он не должен удалить ваши указатели. Все таки это неуправляемый код.

По всей видимости, необходимо выделить память для каждого элемента массива.
Код

IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(int));
Marshal.WriteInt32(result, 0);
d[0] = (int*)result;

не уверен но наверно как то так.

а освобождать память примерно так:
Код

Marshal.FreeHGlobal((IntPtr)d[0]);

PM MAIL   Вверх
magesi
  Дата 27.6.2012, 03:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 20.5.2012

Репутация: нет
Всего: -4



erm0l0v, спасибо за качественный и развернутый ответ  smile очень помогли!
PM MAIL   Вверх
Экскалупатор
Дата 27.6.2012, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(magesi @  8.6.2012,  05:20 Найти цитируемый пост)
а в понимании работы с указателями именно на Шарпе

а для чего, если не секрет? переписал бы уже полностью на шарп. без красивых плюшек но и без "указателей". они все равно будут, так как ссылочные типы никуда не деваются, но будет уже именно шарп и будут именно шарповые ссылочные типы, а не кусок си завернутый в шарп.
PM MAIL ICQ   Вверх
magesi
  Дата 28.6.2012, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 20.5.2012

Репутация: нет
Всего: -4



Цитата(Экскалупатор @  27.6.2012,  22:26 Найти цитируемый пост)
а для чего, если не секрет? переписал бы уже полностью на шарп. без красивых плюшек но и без "указателей". они все равно будут, так как ссылочные типы никуда не деваются, но будет уже именно шарп и будут именно шарповые ссылочные типы, а не кусок си завернутый в шарп. 

типичный русский вопрос "для чего"  smile 

для более лучшего понимания всех тонкостей Шарпа, включая и unmanaged часть

и не надо мне там про "переписал на Шарп", что среди шарпистов указатели и полное избежение unmanaged культируется, я знаю smile

Цитата(Экскалупатор @  27.6.2012,  22:26 Найти цитируемый пост)
ссылочные типы никуда не деваются

ссылки в шарпе, совсем не ссылки, на самом деле ( в отличии от тех же С/С++ )

там нет такого понятия, как независимая ссылка

в Шарпе уровней абстракций уже столько, что понятие "ссылка" в С# уже выглядит не то, как нечто экономичное в плане ресурсов/удобств по обращению по этой ссылке...

скорее правильнее "унарным оператором" назвать, а не ссылкой

Это сообщение отредактировал(а) magesi - 28.6.2012, 23:33
PM MAIL   Вверх
Экскалупатор
Дата 28.6.2012, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(magesi @  28.6.2012,  12:40 Найти цитируемый пост)
для более лучшего понимания всех тонкостей Шарпа, включая и unmanaged часть

есть такой вопрос/поговорка: почему собака лижет свои яйца? потому что может!

вопрос о том ссылка там или еще чего это риторика. сути это не меняет. большинство моих знакомых, категорически против использования unmanaged вставок. как то у них не сложилось. не шарповое это, больше проблем получаешь из-за него в проекте. хотя конечно все это имхо, но мне кажется уже лучше делать отдельную библиотеку на С++ и подключать.
я просто пытаюсь сказать что логичнее было бы писать используя то что предоставляет платформа, не смешивая разные платформы в одном месте. а то будут появляться вопросы типа: а как мне ввернуть лампочку используя лопату?
PM MAIL ICQ   Вверх
magesi
  Дата 28.6.2012, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 20.5.2012

Репутация: нет
Всего: -4



Цитата(Экскалупатор @  28.6.2012,  18:26 Найти цитируемый пост)
вопрос о том ссылка там или еще чего это риторика. сути это не меняет. большинство моих знакомых, категорически против использования unmanaged вставок. как то у них не сложилось. не шарповое это, больше проблем получаешь из-за него в проекте. хотя конечно все это имхо, но мне кажется уже лучше делать отдельную библиотеку на С++ и подключать.

лучше вообще шарп, джаву и всякое  smile не юзать, а то извратили все


Цитата(Экскалупатор @  28.6.2012,  18:26 Найти цитируемый пост)
не шарповое это

"не прикладное"


Цитата(Экскалупатор @  28.6.2012,  18:26 Найти цитируемый пост)
больше проблем получаешь из-за него в проекте

ну да, более ручное управление тяжелее сразу


Цитата(Экскалупатор @  28.6.2012,  18:26 Найти цитируемый пост)
есть такой вопрос/поговорка: почему собака лижет свои яйца? потому что может!

нерелевантно в данном случае, чтобы нормально тот же КМП реализовать ( в плане оптимизации ) нужно память вручную контроллировать ( в целом, как и другие классические алгоритмы, у которых есть четкая асиптота по скорости выполнения, а Шарп всю эту асиптоту сильно кривит , что любое O(n log n) станет O(n^3)  smile

вот Вам и ответ для чего, когда берешься реализовать нормально алгоритм, нужно все факторы учитывать, как: когерентность процессов, работу с потоками, памятью, а также др. оценок

в шарпе с набором слоя абстракции на другой абстракции все сильно ухудиштся в плане и оптимизации и производительности, а для ряда алгоритмов это критично, если очень много данных, как несколько милионов

и тут лошади яица, как Вы выразились, не лижут, скорее стрижку лобка устраивают  smile 

Это сообщение отредактировал(а) magesi - 28.6.2012, 23:56
PM MAIL   Вверх
Экскалупатор
Дата 28.6.2012, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(magesi @  28.6.2012,  21:42 Найти цитируемый пост)
нерелевантно в данном случае, чтобы нормально тот же КМП реализовать ( в плане оптимизации ) нужно память вручную контроллировать ( в целом, как и другие классические алгоритмы, у которых есть четкая асиптота по скорости выполнения, а Шарп всю эту асиптоту сильно кривит , что любое O(n log n) станет O(n^3)  smile

вот Вам и ответ для чего, когда берешься реализовать нормально алгоритм, нужно все факторы учитывать, как: когерентность процессов, работу с потоками, памятью, а также др. оценок

в шарпе с набором слоя абстрации на другой абстрации все сильно ухудиштся в плане и оптимизации и производительности, а для ряда алгоритмов это критично, если очень много данных, как несколько милионов


))) так я ж об этом же и говорю! все совершенно верно! если нужно все это и шарп для этого не подходит то... нужно сразу взять то что подходит!!! это же очевидное решение. не нужно смешивать. я именно это и имел ввиду!
PM MAIL ICQ   Вверх
magesi
  Дата 28.6.2012, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 20.5.2012

Репутация: нет
Всего: -4



Экскалупатор, почему? И на Шарпе можно реализовать такое , если знать как управлять всем вручную и сколько требуется ресурсов на то или иное действие и что под капотом шарпа происходит, поэтому я как раз и спросил такой вопрос про unmanaged часть, такой тип указателей и прочее smile 

Это сообщение отредактировал(а) magesi - 29.6.2012, 09:53
PM MAIL   Вверх
erm0l0v
Дата 29.6.2012, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: 1
Всего: 1



Да действительно на C# можно использовать неуправляемый код, но выглядит это немого коряво. Просто в действительности мест где мы можем использовать неуправляемый код не так много, например нужно вызвать какую нибудь WinAPI функцию с хитрой структурой, или написать эффективный алгоритм. И переходить ради этих мелочей на другой язык мне кажется не очень оправданно. И создать в солюшене проекты на разных языках мне кажется не лучшей идеей, особенно в корпоративных проектах.

Кстати вот неплохая статья про работу с указателями. И полезная wiki про использование WinAPI в C# и VB возможно пригодится.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.2750 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.