C MultiThread Value not printed - c

First, Here is an entire code.
Read the file
Input file content into structure value
Begin Multithread
$ cat sunje.conf
{
DSN:GOLDILOCKS
UID:TEST
PWD:test
COMMIT INTERVAL:1
}
$ cat sh.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
//EXEC SQL INCLUDE SQLCA;
typedef struct thread
{
char *dsn;
char *uid;
char *pwd;
char mode;
int num;
int start;
int end;
int interval;
} thread;
pthread_mutex_t mutex;
void *MultiThread(void* threadInfo);
int main(int argc, char **argv)
{
char s[1024];
FILE *fp;
char conn[4][1024];
int i = 0;
int session = 0;
int record = 0;
char mode = NULL;
//int interval;
fp = fopen("sunje.conf", "r");
while(!feof(fp))
{
fgets(s, 1024, fp);
char *ptr = strchr(s, ':');
if (ptr != NULL)
{
strcpy(conn[i], ptr + 1);
conn[i][strlen(conn[i]) - 1] = '\0';
//printf("conn[%d]=\"%s\"\n", i, conn[i]);
i++;
}
}
fclose(fp);
session = atoi(argv[1]);
record = atoi(argv[2]);
mode = argv[4][0];
printf("=========================================\n");
printf("DSN = [%s]\n"
"ID = [%s]\n"
"PW = [%s]\n"
"Commit Interval = [%s]\n"
"\n"
"Total Session = %d\n"
"Total Record = %d\n"
"Mode = %c\n", conn[0], conn[1], conn[2], conn[3], session, record, mode);
printf("=========================================\n");
int init = 1;
int init_div = record / session ;
int init_mod = record % session ;
if (mode == 's')
{
init = record;
init_div = 0;
}
pthread_mutex_init(&mutex, NULL);
thread threadInfo[session];
pthread_t threadCount[session];
i = 0;
for ( i = 0 ; i < session ; i ++)
{
pthread_mutex_lock(&mutex);
if( i != ( session - 1 ) )
{
threadInfo[i].dsn = conn[0];
threadInfo[i].uid = conn[1];
threadInfo[i].pwd = conn[2];
threadInfo[i].interval = atoi(conn[3]);
threadInfo[i].mode = mode;
threadInfo[i].num = i;
threadInfo[i].start = init;
threadInfo[i].end = init + init_div - 1;
}else
{
threadInfo[i].dsn = conn[0];
threadInfo[i].uid = conn[1];
threadInfo[i].pwd = conn[2];
threadInfo[i].interval = atoi(conn[3]);
threadInfo[i].mode = mode;
threadInfo[i].num = i;
threadInfo[i].start = init;
threadInfo[i].end = init + init_div + init_mod - 1;
}
pthread_mutex_unlock(&mutex);
printf("Thread Num = [%d]\n"
"Mode = [%c]\n"
"Start = [%d]\n"
"End = [%d]\n"
"Interval = [%d]\n"
"DSN = [%s]\n\n"
,threadInfo[i].num, threadInfo[i].mode, threadInfo[i].start, threadInfo[i].end, threadInfo[i].interval, threadInfo[i].dsn);
pthread_create ( &threadCount[i], NULL, MultiThread, (void*)&threadInfo[i] );
init = init + init_div;
}
int result;
i = 0;
for ( i = 0 ; i < session ; i ++)
{
pthread_join ( threadCount[i], (void *)&result );
}
printf("Thread Success\n");
return 0;
}
void *MultiThread(void* threadInfo)
{
thread* info = (thread*)threadInfo;
// struct timeval st, et;
char mode;
int num;
int start;
int end;
int interval;
mode = info->mode;
num = info->num;
start = info->start;
end = info->end;
interval = info->interval;
printf("num[%d] dsn[%s] uid[%s] pwd[%s] mode[%c] interval[%d] start[%d] end[%d]\n", num, info->dsn, info->uid, info->pwd, mode, interval, start, end);
return NULL;
}
Now, I ask a question..
I want to print last thread's value. But only "dsn" value not printed..
I used mutex of pthread to solve this problem. But it was not.
$ ./sh 3 300 2 i
=========================================
DSN = [GOLDILOCKS]
ID = [TEST]
PW = [test]
Commit Interval = [1]
Total Session = 3
Total Record = 300
Mode = i
=========================================
Thread Num = [0]
Mode = [i]
Start = [1]
End = [100]
Interval = [1]
DSN = [GOLDILOCKS]
Thread Num = [1]
Mode = [i]
Start = [101]
End = [200]
Interval = [1]
DSN = [GOLDILOCKS]
num[0] dsn[GOLDILOCKS] uid[TEST] pwd[test] mode[i] interval[1] start[1] end[100]
Thread Num = [2]
Mode = [i]
Start = [201]
End = [300]
Interval = [1]
DSN = [GOLDILOCKS]
num[1] dsn[GOLDILOCKS] uid[TEST] pwd[test] mode[i] interval[1] start[101] end[200]
num[2] dsn[] uid[TEST] pwd[test] mode[i] interval[1] start[201] end[300]
Thread Success
Could you help me?
I can't understand why num[2]'s dsn is not show

int result is 4 bytes.
(void *)&result is 8 bytes.
If the memory structure made like [ int 4 byte result ][ conn[0][0] .. ] .. on first time,
the return will be like [ 8 byte (void **)&result ][ conn[0][4] .. ] ..
Where is conn[0][0] ~ conn[0][3] ? this location covered with NULL(\000).
This program doesn't read after NULL value.
Here is gdb result.
Breakpoint 1, main (argc=5, argv=0x7fffffffdbf8) at sh.gc:131
131 pthread_join ( threadCount[i], (void **)&result );
1: conn[0] = "\000\000\000\000GOLDILOCKS", '\000' <repeats 26 times>, "\364G\336\367\377\177\000\000\000"
(gdb) p &conn[0]
$1 = (char (*)[50]) 0x7fffffffd5c0
(gdb) p &result
$2 = (int *) 0x7fffffffd5bc
(gdb)

Related

Core dump generates when Sytemd starts a c program that opens a link every few hours

I am trying to write a program that opens up the google meet link for a particular class four minutes before it starts.
The program works perfectly fine when I run it directly from the command line, but when I launch it using a systemd service, it fails with a core-dump error.
here is the service file:
[Unit]
Description=Simple G Meet Autojoiner
Wants=network.target
After=syslog.target network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/sgma
[Install]
WantedBy=multi-user.target
here is the program it's trying to launch:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <libnotify/notify.h>
typedef struct {
int hour;
int min;
char *sub;
char *link;
} Class;
const char FILE_NAME[] = "/schedule.txt";
const int NUM_CLASSES = 24;
void notify(char *class_name)
{
notify_init ("Joining Class");
NotifyNotification * Hello = notify_notification_new (class_name, "Starting in a few mins", "dialog-information");
notify_notification_show (Hello, NULL);
g_object_unref(G_OBJECT(Hello));
notify_uninit();
}
void get_schedule(FILE *file, Class schedule[NUM_CLASSES], int current_day)
{
char line[100];
int hour;
char dayfound = 0;
while(fgets(line, sizeof(line), file)) {
if ((line[0] == '[' && atoi(&line[1]) == current_day)) {
dayfound = 1;
continue;
}
/* Ignore the rest of the file */
if (dayfound && line[0] == '\n') {
dayfound = 0;
break;
}
if (dayfound) {
hour = atoi(strtok(line, ":"));
schedule[hour - 9].hour = hour;
schedule[hour - 9].min = atoi(strtok(NULL, "\t"));
schedule[hour - 9].sub = strdup(strtok(NULL, "\t")); /* We copy it first because strtok returns a pointer */
schedule[hour - 9].link = strdup(strtok(NULL, "\t"));
}
}
}
void join_meet(Class schedule[NUM_CLASSES], time_t now)
{
struct tm *current_local;
int cur_min;
int cur_hour;
int min_left;
for (int i = 0; i < NUM_CLASSES; ++i) {
now = time(NULL);
current_local = localtime(&now);
cur_min = current_local->tm_min;
cur_hour = current_local->tm_hour;
if (schedule[i].hour != -1) {
if (cur_hour <= schedule[i].hour) {
min_left = (schedule[i].hour - cur_hour) * 60 + schedule[i].min - cur_min - 4;
if (min_left < 0) continue;
sleep(min_left * 60);
if (fork() == 0) {
notify(schedule[i].sub);
execlp("xdg-open", "xdg-open", schedule[i].link, NULL);
}
}
}
}
}
int main()
{
time_t now = time(NULL);
struct tm *local = localtime(&now);
int current_day = local->tm_wday;
char full_path[100];
strcpy(full_path, getenv("XDG_DATA_HOME"));
strncat(full_path, FILE_NAME, 100 - strlen(full_path) - 1);
FILE *file = fopen(full_path, "r");
if (file == NULL) {
perror(full_path);
exit(EXIT_FAILURE);
}
Class schedule[NUM_CLASSES];
for (int i = 0; i < NUM_CLASSES; ++i)
schedule[i].hour = -1;
get_schedule(file, schedule, current_day);
fclose(file);
join_meet(schedule, now);
return 0;
}

Segmentation fault after calling, but a very similar function does not get a segmentation fault error

For one of my CS classes we are creating a mini EXT2 file system. In this program I have to make the functions mkdir and creat. In both these functions we call a function called iput which looks like this:
int iput(MINODE *mip)
{
// dispose of minode pointed by mip
// Code in Chapter 11.7.2
INODE *ip;
int i, block, offset;
char buf[BLKSIZE];
if (mip==0)
{
return;
}
mip->refCount--;
printf("mip->refcount = %d\n", mip->refCount);
if (mip->refCount > 0)
{
return 0;
}
if (mip->dirty == 0)
{
return 0;
}
// dec refCount by 1
// still has user
// no need to write back
// write INODE back to disk
block = (mip->ino - 1) / 8 + inode_start;
offset = (mip->ino - 1) % 8;
// get block containing this inode
get_block(mip->dev, block, buf);
printf("get block works in iput\n");
ip = (INODE *)buf + offset; // ip points at INODE
*ip = mip->inode; // copy INODE to inode in block
put_block(mip->dev, block, buf); // write back to disk
printf("put block works in iput\n");
//midalloc(mip); //
mip->refCount = 0;
return 1;
}
Minode is just a struct wrapper that holds an inode inside it, along with other variables. Here is the code for my creat function:
int my_creat(MINODE *pip, char *name)
{
MINODE *mip;
int ino = ialloc(pip->dev);
int bno = balloc(pip->dev);
mip = iget(dev,ino);
INODE *ip = &mip->inode;
ip->i_mode = 0x81A4;
ip->i_uid = running->uid;
ip->i_gid = running->gid;
ip->i_size = 0;
ip->i_links_count = 1;
ip->i_atime = time(0L);
ip->i_ctime = time(0L);
ip->i_mtime = time(0L);
ip->i_blocks = 2;
ip->i_block[0] = bno;
for (int i = 1; i < 15; i++)
{
ip->i_block[i] = 0;
}
mip->dirty = 1;
iput(mip);
char buf[BLKSIZE];
dp = (DIR *)buf;
dp->inode = ino;
strncpy(dp->name, ".", 1);
dp->name_len = 1;
dp->rec_len = 12;
char *cp;
cp = buf + 12;
dp = (DIR*)cp;
dp->inode = pip->ino;
dp->name_len = 2;
strncpy(dp->name, "..", 2);
dp->rec_len = BLKSIZE - 12;
put_block(pip->dev,bno,buf);
enter_name(pip,ino,name);
}
And here is the code for my mkdir function:
int mymkdir(MINODE *pip, char *name)
{
MINODE *mip;
int ino = ialloc(pip->dev);
int bno = balloc(pip->dev);
printf("bno inside mymkdir = %d\n", bno);
printf("ino inside mymkdir = %d\n", ino);
char buf[BLKSIZE];
mip = iget(dev,ino);
printf("goes over iget again\n");
INODE *ip = &mip->inode;
ip->i_mode = 0x41ED;
ip->i_uid = running->uid;
ip->i_gid = running->gid;
ip->i_size = BLKSIZE;
ip->i_links_count = 2;
ip->i_atime = time(0L);
ip->i_ctime = time(0L);
ip->i_mtime = time(0L);
ip->i_blocks = 2;
ip->i_block[0] = bno;
for (int i = 1; i < 15; i++)
{
ip->i_block[i] = 0;
}
mip->dirty = 1;
iput(mip);
printf("goes over iput");
dp = (DIR *)buf;
dp->inode = ino;
strncpy(dp->name, ".", 1);
dp->name_len = 1;
dp->rec_len = 12;
char *cp;
cp += dp->rec_len;
dp = (DIR*)cp;
dp->inode = pip->ino;
dp->name_len = 2;
strncpy(dp->name, "..",2);
dp->rec_len = BLKSIZE - 12;
put_block(pip->dev,bno,buf);
enter_name(pip,ino,name);
}
They are virtually the exact same, but for whatever reason after calling iput in mkdir it crashes and gives me a segmentation fault error, however that does not happen in my creat function. This makes no sense as they are virtually the exact same functions and thus one shouldn't be working if the other isn't working too. Also, they are in the same file, mkdir_creat.c, but the iput function is inside a different C file, and im running it through the linux terminal by using gcc main.c mkdir_creat.c etc. Any help on to why the mkdir function is giving a segmentation fault error would be much appreciated! Thank you!

How to create a list of word with specific length

Im currently writing a C programming to create a list of word with specific length.
For example, I have a string of ten letter
ABCDEFGHIJ
and wanted to create a list of word where the length is 2 that is
AB,BC,CD,DE,EF,FG,GH,HI,IJ.
For now I can only create
AB,CD,EF,GH,IJ
with my coding
#include<stdio.h>
#include<string.h>
int main()
{
/*q=length of query sequence, W=length of substring, t=(q-w)+1*/
char array[5][3],length[3];
int i=1;
FILE *input;
input=fopen("string.txt", "r");
/*stores and prints the data from the string*/
while(fgets(length,3,input))
{
strcpy(array[i],length);
printf(">%d\n%s\n\n",i,array[i]);
i++;
}
return 0;
}
How can I point the array to starts the next word at position from the second letter not the third letter?
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char wmers[115];
int i = 1, j = 2;
FILE *input = NULL;
FILE *output;
if (!(input = fopen("exon11.txt", "r"))) {
// Error
return (EXIT_FAILURE);
}
if (!fgets(wmers,115,input)) {
// Error ?
}
printf(">%d\n%s\n\n",i,wmers);
i++;
output=fopen("2.txt", "w");
fputs(wmers,output);
for(int c = fgetc(input); c != EOF; c = fgetc(input))
{
wmers[0] = wmers[1];
wmers[1] = wmers[2];
wmers[2] = wmers[3];
wmers[3] = wmers[4];
wmers[4] = wmers[5];
wmers[5] = wmers[6];
wmers[6] = wmers[7];
wmers[7] = wmers[8];
wmers[8] = wmers[9];
wmers[9] = wmers[10];
wmers[10] = wmers[11];
wmers[11] = wmers[12];
wmers[12] = wmers[13];
wmers[13] = wmers[14];
wmers[14] = wmers[15];
wmers[15] = wmers[16];
wmers[16] = wmers[17];
wmers[17] = wmers[18];
wmers[18] = wmers[19];
wmers[19] = wmers[20];
wmers[20] = wmers[21];
wmers[21] = wmers[22];
wmers[22] = wmers[23];
wmers[23] = wmers[24];
wmers[24] = wmers[25];
wmers[25] = wmers[26];
wmers[26] = wmers[27];
wmers[27] = wmers[28];
wmers[28] = wmers[29];
wmers[29] = wmers[30];
wmers[30] = wmers[31];
wmers[31] = wmers[32];
wmers[32] = wmers[33];
wmers[33] = wmers[34];
wmers[34] = wmers[35];
wmers[35] = wmers[36];
wmers[36] = wmers[37];
wmers[37] = wmers[38];
wmers[38] = wmers[39];
wmers[39] = wmers[40];
wmers[40] = wmers[41];
wmers[41] = wmers[42];
wmers[42] = wmers[43];
wmers[43] = wmers[44];
wmers[44] = wmers[45];
wmers[45] = wmers[46];
wmers[46] = wmers[47];
wmers[47] = wmers[48];
wmers[48] = wmers[49];
wmers[49] = wmers[50];
wmers[50] = wmers[51];
wmers[51] = wmers[52];
wmers[52] = wmers[53];
wmers[53] = wmers[54];
wmers[54] = wmers[55];
wmers[55] = wmers[56];
wmers[56] = wmers[57];
wmers[57] = wmers[58];
wmers[58] = wmers[59];
wmers[59] = wmers[60];
wmers[60] = wmers[61];
wmers[61] = wmers[62];
wmers[62] = wmers[63];
wmers[63] = wmers[64];
wmers[64] = wmers[65];
wmers[65] = wmers[66];
wmers[66] = wmers[67];
wmers[67] = wmers[68];
wmers[68] = wmers[69];
wmers[69] = wmers[70];
wmers[70] = wmers[71];
wmers[71] = wmers[72];
wmers[72] = wmers[73];
wmers[73] = wmers[74];
wmers[74] = wmers[75];
wmers[75] = wmers[76];
wmers[76] = wmers[77];
wmers[77] = wmers[78];
wmers[78] = wmers[79];
wmers[79] = wmers[80];
wmers[80] = wmers[81];
wmers[81] = wmers[82];
wmers[82] = wmers[83];
wmers[83] = wmers[84];
wmers[84] = wmers[84];
wmers[85] = wmers[86];
wmers[86] = wmers[87];
wmers[87] = wmers[88];
wmers[88] = wmers[89];
wmers[89] = wmers[90];
wmers[90] = wmers[91];
wmers[91] = wmers[92];
wmers[92] = wmers[93];
wmers[93] = wmers[94];
wmers[94] = wmers[95];
wmers[95] = wmers[96];
wmers[96] = wmers[97];
wmers[97] = wmers[98];
wmers[98] = wmers[99];
wmers[99] = wmers[100];
wmers[100] = wmers[101];
wmers[101] = wmers[102];
wmers[102] = wmers[103];
wmers[103] = wmers[104];
wmers[104] = wmers[105];
wmers[105] = wmers[106];
wmers[106] = wmers[107];
wmers[107] = wmers[108];
wmers[108] = wmers[109];
wmers[109] = wmers[110];
wmers[110] = wmers[111];
wmers[111] = wmers[112];
wmers[112] = wmers[113];
wmers[113] = wmers[114];
wmers[114] = c;
printf(">%d\n%s\n\n",j,wmers);
j++;
fputs(wmers,output);
}
return (EXIT_SUCCESS);
}
this is the content of exon11.txt.
CTGCTTGTGAATTTTCTGAGACGGATGTAACAAATACTGAACATCATCAACCCAGTAATAATGATTTGAACACCACTGAGAAGCGTGCAGCTGAGAGGCATCCAGAAAAGTATCAGGGTAGTTCTGTTTCAAACTTGCATGTGGAGCCATGTGGCACAAATACTCATGCCAGCTCATTACAGCATGAGAACAGCAGTTTATTACTCACTAAAGACAGAATGAATGTAGAAAAGGCTGAATTCTGTAATAAAAGCAAACAGCCTGGCTTAGCAAGGAGCCAACATAACAGATGGGCTGGAAGTAAGGAAACATGTAATGATAGGCGGACTCCCAGCACAGAAAAAAAGGTAGATCTGAATGCTGATCCCCTGTGTGAGAGAAAAGAATGGAATAAGCAGAAACTGCCATGCTCAGAGAATCCTAGAGATACTGAAGATGTTCCTTGGATAACACTAAATAGCAGCATTCAGAAAGTTAATGAGTGGTTTTCCAGAAGTGATGAACTGTTAGGTTCTGATGACTCACATGATGGGGAGTCTGAATCAAATGCCAAAGTAGCTGATGTATTGGACGTTCTAAATGAGGTAGATGAATATTCTGGTTCTTCAGAGAAAATAGACTTACTGGCCAGTGATCCTCATGAGGCTTTAATATGTAAAAGTGAAAGAGTTCACTCCAAATCAGTAGAGAGTAATATTGAAGACAAAATATTTGGGAAAACCTATCGGAAGAAGGCAAGCCTCCCCAACTTAAGCCATGTAACTGAAAATCTAATTATAGGAGCATTTGTTACTGAGCCACAGATAATACAAGAGCGTCCCCTCACAAATAAATTAAAGCGTAAAAGGAGACCTACATCAGGCCTTCATCCTGAGGATTTTATCAAGAAAGCAGATTTGGCAGTTCAAAAGACTCCTGAAATGATAAATCAGGGAACTAACCAAACGGAGCAGAATGGTCAAGTGATGAATATTACTAATAGTGGTCATGAGAATAAAACAAAAGGTGATTCTATTCAGAATGAGAAAAATCCTAACCCAATAGAATCACTCGAAAAAGAATCTGCTTTCAAAACGAAAGCTGAACCTATAAGCAGCAGTATAAGCAATATGGAACTCGAATTAAATATCCACAATTCAAAAGCACCTAAAAAGAATAGGCTGAGGAGGAAGTCTTCTACCAGGCATATTCATGCGCTTGAACTAGTAGTCAGTAGAAATCTAAGCCCACCTAATTGTACTGAATTGCAAATTGATAGTTGTTCTAGCAGTGAAGAGATAAAGAAAAAAAAGTACAACCAAATGCCAGTCAGGCACAGCAGAAACCTACAACTCATGGAAGGTAAAGAACCTGCAACTGGAGCCAAGAAGAGTAACAAGCCAAATGAACAGACAAGTAAAAGACATGACAGCGATACTTTCCCAGAGCTGAAGTTAACAAATGCACCTGGTTCTTTTACTAAGTGTTCAAATACCAGTGAACTTAAAGAATTTGTCAATCCTAGCCTTCCAAGAGAAGAAAAAGAAGAGAAACTAGAAACAGTTAAAGTGTCTAATAATGCTGAAGACCCCAAAGATCTCATGTTAAGTGGAGAAAGGGTTTTGCAAACTGAAAGATCTGTAGAGAGTAGCAGTATTTCATTGGTACCTGGTACTGATTATGGCACTCAGGAAAGTATCTCGTTACTGGAAGTTAGCACTCTAGGGAAGGCAAAAACAGAACCAAATAAATGTGTGAGTCAGTGTGCAGCATTTGAAAACCCCAAGGGACTAATTCATGGTTGTTCCAAAGATAATAGAAATGACACAGAAGGCTTTAAGTATCCATTGGGACATGAAGTTAACCACAGTCGGGAAACAAGCATAGAAATGGAAGAAAGTGAACTTGATGCTCAGTATTTGCAGAATACATTCAAGGTTTCAAAGCGCCAGTCATTTGCTCCGTTTTCAAATCCAGGAAATGCAGAAGAGGAATGTGCAACATTCTCTGCCCACTCTGGGTCCTTAAAGAAACAAAGTCCAAAAGTCACTTTTGAATGTGAACAAAAGGAAGAAAATCAAGGAAAGAATGAGTCTAATATCAAGCCTGTACAGACAGTTAATATCACTGCAGGCTTTCCTGTGGTTGGTCAGAAAGATAAGCCAGTTGATAATGCCAAATGTAGTATCAAAGGAGGCTCTAGGTTTTGTCTATCATCTCAGTTCAGAGGCAACGAAACTGGACTCATTACTCCAAATAAACATGGACTTTTACAAAACCCATATCGTATACCACCACTTTTTCCCATCAAGTCATTTGTTAAAACTAAATGTAAGAAAAATCTGCTAGAGGAAAACTTTGAGGAACATTCAATGTCACCTGAAAGAGAAATGGGAAATGAGAACATTCCAAGTACAGTGAGCACAATTAGCCGTAATAACATTAGAGAAAATGTTTTTAAAGAAGCCAGCTCAAGCAATATTAATGAAGTAGGTTCCAGTACTAATGAAGTGGGCTCCAGTATTAATGAAATAGGTTCCAGTGATGAAAACATTCAAGCAGAACTAGGTAGAAACAGAGGGCCAAAATTGAATGCTATGCTTAGATTAGGGGTTTTGCAACCTGAGGTCTATAAACAAAGTCTTCCTGGAAGTAATTGTAAGCATCCTGAAATAAAAAAGCAAGAATATGAAGAAGTAGTTCAGACTGTTAATACAGATTTCTCTCCATATCTGATTTCAGATAACTTAGAACAGCCTATGGGAAGTAGTCATGCATCTCAGGTTTGTTCTGAGACACCTGATGACCTGTTAGATGATGGTGAAATAAAGGAAGATACTAGTTTTGCTGAAAATGACATTAAGGAAAGTTCTGCTGTTTTTAGCAAAAGCGTCCAGAAAGGAGAGCTTAGCAGGAGTCCTAGCCCTTTCACCCATACACATTTGGCTCAGGGTTACCGAAGAGGGGCCAAGAAATTAGAGTCCTCAGAAGAGAACTTATCTAGTGAGGATGAAGAGCTTCCCTGCTTCCAACACTTGTTATTTGGTAAAGTAAACAATATACCTTCTCAGTCTACTAGGCATAGCACCGTTGCTACCGAGTGTCTGTCTAAGAACACAGAGGAGAATTTATTATCATTGAAGAATAGCTTAAATGACTGCAGTAACCAGGTAATATTGGCAAAGGCATCTCAGGAACATCACCTTAGTGAGGAAACAAAATGTTCTGCTAGCTTGTTTTCTTCACAGTGCAGTGAATTGGAAGACTTGACTGCAAATACAAACACCCAGGATCCTTTCTTGATTGGTTCTTCCAAACAAATGAGGCATCAGTCTGAAAGCCAGGGAGTTGGTCTGAGTGACAAGGAATTGGTTTCAGATGATGAAGAAAGAGGAACGGGCTTGGAAGAAAATAATCAAGAAGAGCAAAGCATGGATTCAAACTTAG
Given your question, you have tor ead your file char by char, not 2 char by 2 char :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[3] = "";
FILE *input = NULL;
if (!(input = fopen("string.txt", "r"))) {
// Error
return (EXIT_FAILURE);
}
if (!fgets(str,3,input)) {
// Error ?
}
printf("%s\n", str);
for(int c = fgetc(input); c != EOF; c = fgetc(input)) {
str[0] = str[1];
str[1] = c;
printf("%s\n", str);
}
return (EXIT_SUCCESS);
}
But a better way is to read the whole line (like with getline if you are on Linux) and simply display 2 char by 2 char ...
----------
Okay, so this is not really how SO work, but I'm gonna give you a piece of code.
But before that, some general advice :
Begin by testing your code with little data.
I mean, doing a test with an input of 10 char and a len of 2 is good, doing a test with an input of 3K+ char and a len of 100+ is insane. How do you expect to see if your code is good or bad ?
Cut your code in small function.
And do some "unitary" test on these function. That way, if something failed, you will be able to quickly found the bug without a debugger. If the function to retrieve data work but you end up with a wrong result, the maybe the problem lies when you construct your solution. If the result's construction work but you end up with bad value in your file, then maybe it's the writing function that is at fault. etc etc.
Use str* function.
Doing a manually shift to the left with a string of len 2 is ok, but doing it with a string of 115 is insane ! How many time did you spend on that ?
This is the piece of code that will take a string as an input an do what you want.
Since the array can have any length, the last value of the array is NULL.
It's like a string : to know the len, you search for the particuliar value '\0'. Here, it's not '\0' but rather NULL.
The result array and the string's result are good thanks to calloc that implictly set all array pointeur to NULL and all string content to \0.
That's why strncpy doesn't fail.
// TODO Do the description
char** Magic(const char * const input, size_t len)
{
char **array = NULL;
size_t arraySize = 0;
size_t inputLen = strlen(input);
char **returnFunction = NULL;
// Basic check (assert ?)
if (!len) {
// TODO Error message
goto END_FUNCTION;
}
// Calcul of the array length
if (len <= inputLen) {
arraySize = inputLen - len + 1;
}
// Last array value must be NULL in order to know the array length
++arraySize;
if (!(array = calloc(arraySize, sizeof(*array)))) {
// TODO Error message
goto END_FUNCTION;
}
for (size_t i = 0; i < arraySize - 1; ++i) {
if (!(array[i] = calloc(len + 1, sizeof(*array[i])))) {
// TODO Error message
goto END_FUNCTION;
}
strncpy(array[i], input + i, len);
}
returnFunction = array;
array = NULL;
/* GOTO */END_FUNCTION:
if (array) {
for (size_t i = 0; i < arraySize; ++i) {
free(array[i]);
}
free(array);
}
return (returnFunction);
}
int main(void)
{
char *input = "ABCDEFGIHJ";
size_t inputLen = strlen(input);
char **result = NULL;
for (size_t len = 1; len <= inputLen; ++len) {
// Get result
if (!(result = Magic(input, len))) {
// TODO error log ?
continue;
}
// Display result
printf("result for %zu len : ", len);
for (size_t i = 0; result[i]; ++i) {
printf("%s%s", result[i], result[i + 1] ? ", " : "\n");
}
// Free result
for (size_t i = 0; result[i]; ++i) {
free(result[i]);
}
free(result);
result = NULL;
}
return (EXIT_SUCCESS);
}
What's left up to you is : retrieving the data (and then use it in the "input" argument) and display/writing the data.
For both of these, DO A FUNCTION.
And test. lot of test.
Do not forget to check if there is a failure when calling a function.

Writing improper number of frames using PortAudio?

Running my program, I appear to not be writing the correct amount of frames according to the index.
$ ./test
Now recording!! Please speak into the microphone.
index = 0
Writing to: test.flac
audio.h:
#include <stdint.h>
#include <string.h>
typedef struct
{
uint32_t duration;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t frameIndex; /* Index into sample array. */
uint32_t maxFrameIndex;
char* recordedSamples;
} AudioData;
int recordFLAC(AudioData* data, const char *fileName);
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <sndfile.h>
#include "audio.h"
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration)
{
AudioData* data = malloc(sizeof(*data));
if (!data) return NULL;
data->duration = duration;
data->format_type = 1;
data->number_of_channels = channels;
data->sample_rate = sample_rate;
data->frameIndex = 0;
data->maxFrameIndex = sample_rate * duration;
data->recordedSamples = malloc(sizeof(data->maxFrameIndex));
if(!data->maxFrameIndex) return NULL;
return data;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
AudioData* data = (AudioData*)userData;
const char* buffer_ptr = (const char*)inputBuffer;
char* index_ptr = &data->recordedSamples[data->frameIndex];
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
if(framesLeft < frameCount){
framesToCalc = framesLeft;
finished = paComplete;
}else{
framesToCalc = frameCount;
finished = paContinue;
}
if(!inputBuffer){
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
}else{
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = *buffer_ptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordFLAC(AudioData* data, const char *fileName)
{
PaStreamParameters inputParameters;
PaStream* stream;
int err = 0;
int totalFrames = data->maxFrameIndex;
int numSamples;
int numBytes;
char max, val;
double average;
numSamples = totalFrames * data->number_of_channels;
numBytes = numSamples;
data->recordedSamples = malloc(numBytes);
if(!data->recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data->recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = data->number_of_channels; /* stereo input */
inputParameters.sampleFormat = data->format_type;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, data->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data->frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data->recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
done:
Pa_Terminate();
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
else
{
SF_INFO sfinfo;
sfinfo.channels = 1;
sfinfo.samplerate = data->sample_rate;
sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
// open to file
printf("Writing to: %s\n", fileName);
SNDFILE * outfile = sf_open(fileName, SFM_WRITE, &sfinfo);
if (!outfile) return -1;
// prepare a 3 second long buffer (sine wave)
const int size = data->sample_rate * 3;
// write the entire buffer to the file
sf_write_raw(outfile, data->recordedSamples, size);
// force write to disk
sf_write_sync(outfile);
// don't forget to close the file
sf_close(outfile);
}
return err;
}
I'm not quite sure where I am going wrong, I know I need to be writing more frames. Any suggestions?
There seems to be something wrong with your assumptions about the sample format. In the callback you are using char * (single bytes) for the sample format, but in your libsndfile call you're opening a 16 bit file with SF_FORMAT_PCM_16.
This is not so good:
data->format_type = 1;
I recommend using one of the symbolic constants in the PortAudio library for sample formatting. Maybe you want a 16 bit one? And if so, you want to be using short* not char* in the PA callback.
Finally, if your channel count is not 1, the copy loops are incorrect:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
A "frame" contains data for all channels, so for example, if it's a stereo input your iteration needs to deal with both left and right channels like this:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0; // left
*index_ptr++ = 0; // right
}
Same for the other loops.

Context Switching using swap context() and a custom yield function

I am writing my own user level thread library and am running into some issues. Below is the code of the library I have written thus far after the edits provided by you guys and also some introspection from my end:
struct tcb {
int thread_id;
int thread_pri;
ucontext_t thread_context;
struct tcb *next;
} *ready_head;
typedef struct tcb tcb;
tcb *running_head;
tcb *tmp,*tmp1,*tmp2,*temp;
// ucontext_t *ready;
// head = NULL;
// running_head = head;
void t_shutdown()
{
free(temp);
free(tmp);
free(tmp1);
free(ready_head);
free(running_head);
}
void t_yield()
{
// tmp2 = ready_head;
tmp1 = running_head;
/* tmp = running_head;
running_head = ready_head;
while(tmp1->next != NULL)
tmp1 = tmp1->next;
tmp1->next = tmp;
*/
insert(tmp1);
running_head = ready_head;
ready_head = ready_head->next;
printf("yield1\n");
swapcontext(&running_head->thread_context, &tmp1->thread_context);
printf("yield2\n");
// setcontext(&ready_head->thread_context);
}
void insert(tcb *a)
{
tcb *b;
if (ready_head == NULL)
{
ready_head = a;
}
else
{
b = ready_head;
while(b->next)
b = b->next;
b->next = a;
}
printf("insert\n");
}
void t_init()
{
tmp = (tcb *)malloc(sizeof(tcb));
getcontext(&tmp->thread_context); /* let tmp be the context of main() */
tmp->next = NULL;
running_head = tmp;
ready_head = NULL;
}
int t_create(void (*fct)(int), int id, int pri)
{
size_t sz = 0x10000;
temp = (tcb *)malloc(sizeof(tcb));
getcontext(&temp->thread_context);
temp->thread_id = id;
temp->thread_pri = pri;
temp->thread_context.uc_stack.ss_sp = malloc(sz); /* new statement */
temp->thread_context.uc_stack.ss_size = sz;
temp->thread_context.uc_stack.ss_flags = 0;
temp->thread_context.uc_link = &tmp->thread_context;
makecontext(&temp->thread_context, fct, 1, id);
insert(temp);
printf("1\n");
}
I am testing this library on the following test program:
void assign(void)
{
int i;
for (i = 0; i < 3; i++)
printf("in assign(1): %d\n", i);
t_yield();
for (i = 10; i < 13; i++)
printf("in assign(2): %d\n", i);
t_yield();
for (i = 20; i < 23; i++)
printf("in assign(3): %d\n", i);
}
int main(int argc, char **argv)
{
t_init();
t_create(assign, 1, 1);
printf("in main(): 0\n");
t_yield();
printf("in main(): 1\n");
t_yield();
printf("in main(): 2\n");
t_yield();
printf("done...\n");
return (0);
}
The expected output is:
in main(): 0
in assign(1): 0
in assign(1): 1
in assign(1): 2
in main(): 1
in assign(2): 10
in assign(2): 11
in assign(2): 12
in main(): 2
in assign(3): 20
in assign(3): 21
in assign(3): 22
done...
However, I am getting:
in main(): 0
in main(): 1
in main(): 2
done...
I now know that there is an issue with the swapcontext() as that does not seem to be working at all. I have tried to use printf statements to debug my program but am still unable to get this to work! Please help ....
It appears to me that in your t_yield() function you are actually swapping the ready_head context with the ready_head context. You might want to try
swapcontext(&tmp->thread_context, &running_head->thread_context);
instead.

Resources