memset() не устанавливает память в c

Я извиняюсь, если мое форматирование неверно, так как это мой первый пост, я не смог найти пост на сайте, посвященный той же проблеме, с которой я столкнулся. Я использую простой C на сервере Ubuntu 12.04. Я пытаюсь объединить несколько строк в одну строку, разделенную Ns. Однако размеры строк и расстояние между строками могут различаться. Была создана структура для хранения позиционных данных в виде нескольких целых чисел, которые можно передать нескольким функциям:

typedef struct pseuInts {  
    int pseuStartPos;  
    int pseuPos;  
    int posDiff;  
    int scafStartPos;  
} pseuInts;  

А также строковая структура:

typedef struct string {  
    char *str;  
    int len;  
} myString;

Поскольку для объединенной строки существуют условия разрыва, было собрано несколько узлов динамически связанного списка, содержащего идентификатор и объединенную строку:

typedef struct entry {  
    myString title;  
    myString seq;  
    struct entry *next;  
} entry;  

Вызов memset выглядит следующим образом:

} else if ((*pseuInts)->pseuPos != (*pseuInts)->scafStartPos) {  
    (*pseuEntry)->seq.str = realloc ((*pseuEntry)->seq.str, (((*pseuEntry)->seq.len) + (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)))); //realloc the string being extended to account for the Ns  
    memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len)), 'N', (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos))); //insert the correct number of Ns
    (*pseuEntry)->seq.len += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //Update the length of the now extended string  
    (*pseuInts)->pseuPos += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //update the position values  
}  

Все они разыменовываются как this else, если решение находится в функции, вызываемой функцией, вызываемой из main, но изменения в структуре pseuEntry необходимо обновить в main, чтобы передать их другой функции для дальнейшей обработки.
Я дважды проверил числа, используемые в pseuInts, вставив несколько команд printf, и они правильно указывают, сколько N нужно добавить, даже если они меняются между разными короткими строками. Однако, когда программа запускается, memset вставляет Ns только при первом вызове. IE:

GATTGT и TAATTTGACT разделены 4 пробелами, и они становятся:
GATTGTNNNNTAATTTGACT

Однако второй раз, когда он вызывается для той же объединенной строки, он не работает. IE:
TAATTTGACT и TCTCC разделены 6 пробелами, поэтому длинная строка должна выглядеть так:

GATTGTNNNNTAATTTGACTNNNNNNTCTCC
но показывает только:
GATTGTNNNNTAATTTGACTTCTCC

Я добавил printfs для отображения объединенной строки непосредственно перед и после memset, и они идентичны в выводе.
Иногда вставка добавляет дополнительные символьные пробелы, но не инициализирует их, поэтому они печатают чепуху (как и следовало ожидать) . IE:

GAATAAANNNNNNNNNNNNNNNNN¬GCTAATG
должно быть
GAATAAANNNNNNNNNNNNNNNNNGCTAATG

Я переключил memset на цикл for или while и получил тот же результат. Я использовал промежуточный char * для перераспределения и все равно получаю тот же результат. Я ищу предложения относительно того, где я должен искать, чтобы попытаться обнаружить ошибку.


person Pallieguy    schedule 25.11.2013    source источник
comment
Отличное описание проблемы, просто трудно увидеть проблему со всем происходящим разыменованием. Может быть, проще устранять неполадки, если вы можете предоставить достаточно минимального кода, чтобы кто-то мог его скомпилировать, собрать и запустить? Легче увидеть, что происходит. sscce   -  person ryyker    schedule 26.11.2013
comment
Это не имеет шансов на компиляцию. pseuInts — это тип в первом блоке кода и переменная в последнем блоке кода.   -  person WhozCraig    schedule 26.11.2013
comment
Любопытно, а что не так с использованием pseuInts.pseuPos вместо (*pseuInts)->pseuPos? (и другие.)   -  person ryyker    schedule 26.11.2013
comment
Поскольку я использую только один набор pseuInts, который я постоянно обновляю во время выполнения, я обозначил его как: pseuInts *curPseuInts = malloc (sizeof (*curPseuInts)); когда он впервые появился, то передал его этим функциям: void updatePseuEntryPosition (entry **pseuEntry, blastnEntry *blastnEntry, string *curChr, pseuInts **pseuInts); void endPseuEntry (запись **запись, строка *chr, pseuInts *pseuInts); Так что это и тип, и переменная. (Я не могу заставить форматирование работать для комментария, извините)   -  person Pallieguy    schedule 26.11.2013
comment
Каковы значения scafStartPos and pseuPos при вызове memset?   -  person Fiddling Bits    schedule 26.11.2013
comment
Вместо того, чтобы везде использовать (*pseuInts), вы можете просто разыменовать указатель один раз в начале функции и поместить его в локальную переменную. Если вы действительно измените то, на что он указывает, установите это перед возвратом из функции. Ваш код очень трудно читать.   -  person Charlie Burns    schedule 26.11.2013
comment
@ryyker Я попытался использовать pseuInts.pseuPos и ​​получил сообщение об ошибке, что я пытался получить доступ к чему-то, что не является частью структуры или объединения.   -  person Pallieguy    schedule 26.11.2013
comment
@BitFiddlingCodeMonkey Они изменяются в другой части кода, чтобы соответствовать позиции в длинной строке, где должна начинаться следующая короткая строка, и последней позиции, добавляемой к объединенной строке, соответственно.   -  person Pallieguy    schedule 26.11.2013
comment
@ Seth_m55 Знаете ли вы, каковы фактические значения scafStartPos и pseuPos? Если они оба одинаковые, memset ничего не установит, верно?   -  person Fiddling Bits    schedule 26.11.2013
comment
@CharlieBurns Прошу прощения за путаницу. При длительном выполнении программа будет иметь более 100 000 коротких строк длиной от 100 до 2 000 000+ символов. Я хотел сохранить как можно больше памяти, поэтому я избегал как можно большего количества переменных. Однако в целях поиска решения я создам один разыменованный набор переменных с уникальными именами и опубликую его, чтобы его было легче читать.   -  person Pallieguy    schedule 26.11.2013
comment
@BitFiddlingCodeMonkey Я сделал отладочную функцию printf() для отображения всех значений pseuInt и математических значений, которые я использую в вызовах memset() и realloc(). Я вставил его прямо в начало else if, и он опубликовал все числа, сколько N должно быть установлено, но Ns не появлялись в другом printf после вызова memset(), отображающего длинную строку   -  person Pallieguy    schedule 26.11.2013


Ответы (2)


Если вы не против рассмотреть совершенно другой подход, я хотел бы предложить следующее:

Насколько я понимаю, вы намерены: заменить существующие пробелы между двумя строками на равное количество "N". memset() (и связанное с ним выделение памяти) – это основной метод выполнения конкатенации.

Описанные вами проблемы с текущими попытками объединения:
1) мусор, встроенный в результирующую строку.
2) пишет "N" в некоторых непредусмотренных местах памяти.
3) "N" не пишется в других предназначенных местах памяти.

Другой подход:

Во-первых: убедитесь, что памяти, выделенной для изменяемой строки, достаточно для хранения результатов
во-вторых: перед попыткой объединения убедитесь, что все строки, подлежащие объединению, \0 завершены.
третье: используйте strcat() и цикл for(;;) для добавления всех "N" и, в конце концов, последующие строки.

например.

for(i=0;i<numNs;i++)//compute numNs with your existing variables 
{
    strcat(firstStr, "N");//Note: "N" is already NULL term. , and strcat() also ensures null term.
}
strcat(firstStr, lastStr); //a null terminated concatenation

Я знаю, что этот подход сильно отличается от того, что вы делали, но он решает по крайней мере проблемы, указанные в вашем описании проблемы. Если это не имеет смысла, пожалуйста, дайте мне знать, и я отвечу на вопросы по мере возможности. (сейчас есть другие проекты)

person ryyker    schedule 25.11.2013
comment
Извините за поздний ответ. Я дважды проверял, сделал ли мой подход то, что вы предложили, и мне не хватало нулевых терминаторов. Я отредактировал свой код, чтобы убедиться, что после каждой редактируемой строки есть «\ 0», и он работает отлично. Спасибо за вашу помощь! - person Pallieguy; 26.11.2013

Глядя на ваш мемсет:

memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len))), ...

Это пункт назначения. Разве не должно быть:

(memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len) + ((*pseuEntry)->seq.pseuStartPos))

В противном случае я упускаю значение pseuInts .

person woolstar    schedule 25.11.2013
comment
Вы можете быть на что-то, в настоящее время, хотя я считаю, что заявленное намерение OP состоит в том, чтобы начать вставлять N в конце seq.str + seq.len для подсчета scafStartOis-pseuPos (аббревиатуры). Я смотрю на это на очень большом экране, где все разложено, и все еще трудно уследить. Некоторый компилируемый код поможет. - person ryyker; 26.11.2013
comment
Извините за задержку ответа. объяснение Райкера точно. Мне нужно добавить достаточно N, чтобы заполнить пространство от последней добавленной строки (удерживаемой псевдопосом) до начала следующей короткой строки (удерживаемой scafStartPos). PseuStartPos используется, когда их позиции перекрываются, IE, если строка X заканчивается в позиции 5, а строка Y начинается в позиции 4, тогда мне нужно создать новую длинную строку и обновить pseuStartPos до 4 вместо одного, чтобы все относительные позиции были настроены на эта новая начальная позиция. - person Pallieguy; 26.11.2013