Problem med C

Avdelningen för programmering, nätverk samt alternativa OS.
Post Reply
User avatar
SBeaver
Posts: 266
Joined: 2002-03-07 23:32:13

Problem med C

Post by SBeaver »

blir arg, jag ska ha en char array i C som ska få sitt värde av hur många tecken jag får in från scanf("%s", &char_arrayen);
Hur fan gör jag??
Jag vill absolut INTE fördefinera hur lång arrayen ska vara.

edit: en sak till, när jag kompilerar i DJGPP blir exe-filerna typ 60kB även om det bara är ett helloworld program, varför ska det bli så jäkla stort?

Edit: Ändrade ämnesraden till något beskrivande. //linc
JoooN
Posts: 45
Joined: 2002-09-07 19:48:48

Post by JoooN »

sizeof(array) kanske..
User avatar
Ancalagon
Posts: 550
Joined: 2002-03-08 14:16:41
Location: Stockholm

Post by Ancalagon »

hehe, du kan inte göra en variable size array i C, eller d.v.s. en aray kan inte ändra storlek under körning ..
I stället kan du t.ex. ha en buffer som är MAX_CHAR lång och sedan skapa en ny array med önskad size ..

"typ:" (orka test kompilera ..)

Code: Select all

#define MAX_INP 1000

...

char tmp_buf[MAX_INP];
char *str;

scanf("%s",tmp_buf);
str = malloc(strlen(tmp_buf));
strncpy(strlen(tmp_buf),str,tmp_buf);

User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Re: Problem med C

Post by IcePic »

SBeaver wrote:blir arg, jag ska ha en char array i C som ska få sitt värde av hur många tecken jag får in från scanf("%s", &char_arrayen);
Hur fan gör jag??
Jag vill absolut INTE fördefinera hur lång arrayen ska vara.
Du har inget val om du håller dig till scanf(), varpå man inser att scanf()
inte är något bra. Använd fgets() istället så får du ange hur många tecken
som max den ska ta in.
edit: en sak till, när jag kompilerar i DJGPP blir exe-filerna typ 60kB även om det bara är ett helloworld program, varför ska det bli så jäkla stort?
Troligen för att det är 59K standard-fluff + 1k för din kod. Så när ditt program
växer så märks standardfluffet mindre och mindre. När du är uppe i MS-Word's
storlek så är det inte ens mätbart. =)
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

Öppna filen, kolla hur lång strängen är(om hela filen = strängen så finns det standard funks). Allockera tillräckligt med minne till en pekare och läs in. Då kommer du alltid få rätt storlek. På detta sättet har kommer du inte begränsas av några jobbiga konstanter eller bufferstorlekar, utan bara om minnet räcker till.
User avatar
Ancalagon
Posts: 550
Joined: 2002-03-08 14:16:41
Location: Stockholm

Post by Ancalagon »

gottegrisen wrote:Öppna filen, kolla hur lång strängen är(om hela filen = strängen så finns det standard funks). Allockera tillräckligt med minne till en pekare och läs in. Då kommer du alltid få rätt storlek. På detta sättet har kommer du inte begränsas av några jobbiga konstanter eller bufferstorlekar, utan bara om minnet räcker till.
hmm, varifrån kommer filen ?
(okej - "allt" i unix är en fil, men man kan väl fortfarande inte förutse hur många tecken som användaren tänker skriva på stdin ??)
;D
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Öppna filen, kolla hur lång strängen är(om hela filen = strängen så finns det standard funks). Allockera tillräckligt med minne till en pekare och läs in. Då kommer du alltid få rätt storlek. På detta sättet har kommer du inte begränsas av några jobbiga konstanter eller bufferstorlekar, utan bara om minnet räcker till.
Som han sa, den tar ju från stdin, så den blir lite svår att förutse. =)
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

Ancalagon wrote:
gottegrisen wrote:Öppna filen, kolla hur lång strängen är(om hela filen = strängen så finns det standard funks). Allockera tillräckligt med minne till en pekare och läs in. Då kommer du alltid få rätt storlek. På detta sättet har kommer du inte begränsas av några jobbiga konstanter eller bufferstorlekar, utan bara om minnet räcker till.
hmm, varifrån kommer filen ?
(okej - "allt" i unix är en fil, men man kan väl fortfarande inte förutse hur många tecken som användaren tänker skriva på stdin ??)
;D

Jag satt och tänkte på fscanf och filer;D

Ne men annars går det ju att räkna antalet tecken som skrivs, backa och sedan köra sin kära scanf med rätt längd. Så slipper man ju konstanter och buffrar, men å andra sidan är det jobbigare.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Jag satt och tänkte på fscanf och filer;D

Ne men annars går det ju att räkna antalet tecken som skrivs, backa och sedan köra sin kära scanf med rätt längd. Så slipper man ju konstanter och buffrar, men å andra sidan är det jobbigare.
Frågan är ju om man kan backa på ett bra sätt i en pipe t.ex?
Vad jag minns så är pipes typ en liten multipel av 512 bytes långa, så börjar
du läsa från pipe:n så kommer du aldrig se mer än 512*x bytes i taget men
totalt sett kan du få 100M den vägen.
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote:
gottegrisen wrote:Jag satt och tänkte på fscanf och filer;D

Ne men annars går det ju att räkna antalet tecken som skrivs, backa och sedan köra sin kära scanf med rätt längd. Så slipper man ju konstanter och buffrar, men å andra sidan är det jobbigare.
Frågan är ju om man kan backa på ett bra sätt i en pipe t.ex?
Vad jag minns så är pipes typ en liten multipel av 512 bytes långa, så börjar
du läsa från pipe:n så kommer du aldrig se mer än 512*x bytes i taget men
totalt sett kan du få 100M den vägen.
Jag förstår inte riktigt vad du menar nu. Stdin är ju en stream som går att hoppa i som i alla streams. Du kanske tänker på vad som visas på skärmen?
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Jag förstår inte riktigt vad du menar nu. Stdin är ju en stream som går att hoppa i som i alla streams. Du kanske tänker på vad som visas på skärmen?
Jag menar att från det att en pipe matar
in 1k in i en pipe (som du kan ta längden på) och att det kommer 1k till så
kan det gå tio dagar eller så.
Så om du kör:
konstigt-program-med-ryckig-output |ditt-prg.exe
och sen har ditt-prg.exe denna pseudo-kod:

Code: Select all

 len=getlength(filehandle) <- t.ex 1k data säger getlength()
 [här multitaskar ditt OS in det andra programmet i x tidsenheter som matar på
 1k till]
 sscanf(filehandle, len) <- risk för att det ligger 2k i stdin nu.
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote:
gottegrisen wrote:Jag förstår inte riktigt vad du menar nu. Stdin är ju en stream som går att hoppa i som i alla streams. Du kanske tänker på vad som visas på skärmen?
Jag menar att från det att en pipe matar
in 1k in i en pipe (som du kan ta längden på) och att det kommer 1k till så
kan det gå tio dagar eller så.
Så om du kör:
konstigt-program-med-ryckig-output |ditt-prg.exe
och sen har ditt-prg.exe denna pseudo-kod:

Code: Select all

 len=getlength(filehandle) <- t.ex 1k data säger getlength()
 [här multitaskar ditt OS in det andra programmet i x tidsenheter som matar på
 1k till]
 sscanf(filehandle, len) <- risk för att det ligger 2k i stdin nu.
Ne, nu måste vi kordinera oss lite :) Jag blir helt förbryllad när du snackar om pipes. För mig är en pipe ett verktyg som gör att man kan kommunicera mellan processer, en process stoppar in och en läser av. Den mottagande processen vet inte vad som är i pipen förren den läst av. Inget sparas i en pipe, utan det är bara ett "rör" som rör sig i FIFO och en byte eller fler och lika många kommer ut. När en användare trycker en tangent, kommer denna skickas via en pipe till den mottagande processen där alla tangenttryckingarna lagras.

Vidare för mig: Till varje (normalt) C program som startar kommer en stream som heter stdin skapas. Stdin är som vilken annan stream som helst förutom att den är fullt buffrad (gäller int stderror dock) och kommer finnas hela tiden programmet lever. Det kommer även skapas två andra strams: stdout och stderror. För två olika program är stdin 2 helt olika strömmar. De är bara en lagringsplats för de tryckingar som användaren gjort när programmet varit aktivt och därmed tagit emot tryckningarna.

Hoppas du håller med mig än så länge :). Så för att återgå till trådens problem. Innan man skall göra den aktuella inläsningen så sätter sparar man positionen med på stdin genom en fgetpos sedan kör man en en loop som räknar upp en variabel så länge som det inte är slut på en string. När slutet på stringen upptäcks, så tillverkar man sin buffer utifrån den längd man erhöll. Sedan sätter positionen på stdin med fsetpos som man erhöll tidigare och slutligen kör man sin fscanf på stdin.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Ne, nu måste vi kordinera oss lite :) Jag blir helt förbryllad när du snackar om pipes. För mig är en pipe ett verktyg som gör att man kan kommunicera mellan processer, en process stoppar in och en läser av. Den mottagande processen vet inte vad som är i pipen förren den läst av. Inget sparas i en pipe, utan det är bara ett "rör" som rör sig i FIFO och en byte eller fler och lika många kommer ut. När en användare trycker en tangent, kommer denna skickas via en pipe till den mottagande processen där alla tangenttryckingarna lagras.
anledningen till att jag blandade in en (shell)pipe var ju för att den får in
data på aynkrona vis, vilket de flesta är med på.
Vidare för mig: Till varje (normalt) C program som startar kommer en stream som heter stdin skapas. Stdin är som vilken annan stream som helst förutom att den är fullt buffrad (gäller int stderror dock) och kommer finnas hela tiden programmet lever. Det kommer även skapas två andra strams: stdout och stderror. För två olika program är stdin 2 helt olika strömmar. De är bara en lagringsplats för de tryckingar som användaren gjort när programmet varit aktivt och därmed tagit emot tryckningarna.

Hoppas du håller med mig än så länge :). Så för att återgå till trådens problem. Innan man skall göra den aktuella inläsningen så sätter sparar man positionen med på stdin genom en fgetpos sedan kör man en en loop som räknar upp en variabel så länge som det inte är slut på en string. När slutet på stringen upptäcks, så tillverkar man sin buffer utifrån den längd man erhöll. Sedan sätter positionen på stdin med fsetpos som man erhöll tidigare och slutligen kör man sin fscanf på stdin.
Men om din process blir utswappad av schedulern MELLAN fsetpos och fscanf
och den processen bakom pipe:n (eller usern som matar stdin) hinner fylla
på med nytt data så kommer fscanf ge MER data än du tidigare hade räknat
med. Och då bombar din buffer och denna race har potential för att bli en
buffer overflow.
Woo, mycket buzzwords där på slutet. =)
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote:
gottegrisen wrote:Ne, nu måste vi kordinera oss lite :) Jag blir helt förbryllad när du snackar om pipes. För mig är en pipe ett verktyg som gör att man kan kommunicera mellan processer, en process stoppar in och en läser av. Den mottagande processen vet inte vad som är i pipen förren den läst av. Inget sparas i en pipe, utan det är bara ett "rör" som rör sig i FIFO och en byte eller fler och lika många kommer ut. När en användare trycker en tangent, kommer denna skickas via en pipe till den mottagande processen där alla tangenttryckingarna lagras.
anledningen till att jag blandade in en (shell)pipe var ju för att den får in
data på aynkrona vis, vilket de flesta är med på.
Vidare för mig: Till varje (normalt) C program som startar kommer en stream som heter stdin skapas. Stdin är som vilken annan stream som helst förutom att den är fullt buffrad (gäller int stderror dock) och kommer finnas hela tiden programmet lever. Det kommer även skapas två andra strams: stdout och stderror. För två olika program är stdin 2 helt olika strömmar. De är bara en lagringsplats för de tryckingar som användaren gjort när programmet varit aktivt och därmed tagit emot tryckningarna.

Hoppas du håller med mig än så länge :). Så för att återgå till trådens problem. Innan man skall göra den aktuella inläsningen så sätter sparar man positionen med på stdin genom en fgetpos sedan kör man en en loop som räknar upp en variabel så länge som det inte är slut på en string. När slutet på stringen upptäcks, så tillverkar man sin buffer utifrån den längd man erhöll. Sedan sätter positionen på stdin med fsetpos som man erhöll tidigare och slutligen kör man sin fscanf på stdin.
Men om din process blir utswappad av schedulern MELLAN fsetpos och fscanf
och den processen bakom pipe:n (eller usern som matar stdin) hinner fylla
på med nytt data så kommer fscanf ge MER data än du tidigare hade räknat
med. Och då bombar din buffer och denna race har potential för att bli en
buffer overflow.
Woo, mycket buzzwords där på slutet. =)
Vi vet att att strängen slutar på ett visst ställe, det var det vi kollade med längden. fscanf kommer läsa från den position som vi satt, tills vi hittar det strängslut som vi redan vet finns på den positionen. Att det sedan skulle dyka upp något nytt tecken efteråt är egalt, strängen är likväl slut på den positionen som vi har beräknat.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Vi vet att att strängen slutar på ett visst ställe, det var det vi kollade med längden.
Men vem garanterar att längden håller sig tills ditt program kommer till raden efter?
[/quote] fscanf kommer läsa från den position som vi satt, tills vi hittar det strängslut som vi redan vet finns på den positionen. Att det sedan skulle dyka upp något nytt tecken efteråt är egalt, strängen är likväl slut på den positionen som vi har beräknat.[/quote]
Nej, fscanf kommer läsa allt den kan, den har ingen längdbegränsning.
Iaf inte om man anger "%s" som format till den.

Men din metod är ju i bästa fall bara en extremt jobbig omskrivning av:
while (finns_tecken())
do
läs X bytes
endwhile

där man itererar över stdin på samma vis som om man kört med read()
från starten, varpå det blir mer eller mindre onödigt att köra hela det här
med fsetpos() och allt eftersom read redan tar längdargument.

Jag upplevde att han ville undvika problem med att få mer data än han
förväntat sig, och med *scanf("%s",kort-string) kan han inte det, punkt.
Oavsett om man söker sig fram och tillbaka och grejar så riskerar han alltid
att stdin innehåller en ISO-image på 650M. Är hans buffer mindre än så och
han använder *scanf() så blir han rökt.
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote: Men vem garanterar att längden håller sig tills ditt program kommer till raden efter?

Nej nu måste du tänka efter lite. Vi vet att vår string börjar antal bytes efter stdin start. Vi räknar antalet bytes vi skall läsa, med vår getc. När vi sedan hittar slutet på stringen vet vi längden som vi skall läsa. Hur i sjutton skulle denna längden kunna ändra sig???? Skall programmet ändra några av våra variabler? Det faktum att avbrotten är avstängda för inmating till stdin gör till och med att det inte kommer finnas några fler teckenen i stdin, men det kan vi bortse från för att inte försvåra för de som kanske inte hänger med.
IcePic wrote: Nej, fscanf kommer läsa allt den kan, den har ingen längdbegränsning.
Iaf inte om man anger "%s" som format till den.
Försöker du slingra dig? Det är ju ganska uppenbart att man skulle ha "%s" när författaren sa att det va en string och jag sa att man skulle kolla var stringslutet var.
IcePic wrote: Men din metod är ju i bästa fall bara en extremt jobbig omskrivning av:
while (finns_tecken())
do
läs X bytes
endwhile
där man itererar över stdin på samma vis som om man kört med read()
från starten, varpå det blir mer eller mindre onödigt att köra hela det här
med fsetpos() och allt eftersom read redan tar längdargument.
getc är ju specialfallet av read där längden är 1, se implementaionen. Om du även skulle använt read med en annan längd än 1 kommer du riskera att läsa in tecken efter ett stringslut. Längden på read är också begränsad av pipen, vilket stdin inte är. Dessutom kan man inte kolla hur många tecken som finns i pipesen, utan man säger till IO enheten att man vill ha avbrottet vid en viss gräns, i fallet getc 1byte. Din omskriving är tvetydigt, vilket gör det svårare för mig att förstå att du tror mitt program skulle vara lättare att skriva. Med läs x bytes menar du att läser från stdin som fil eller med read på pipen?
IcePic wrote: Jag upplevde att han ville undvika problem med att få mer data än han
förväntat sig, och med *scanf("%s",kort-string) kan han inte det, punkt.
Oavsett om man söker sig fram och tillbaka och grejar så riskerar han alltid
att stdin innehåller en ISO-image på 650M. Är hans buffer mindre än så och
han använder *scanf() så blir han rökt.
Man kan ju fråga sig vilket troll sätter sig och skriver 650M på stdin :)
Nåväl med *scanf("%s",rätt-string) kan han det, punkt.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:
IcePic wrote: Men vem garanterar att längden håller sig tills ditt program kommer till raden efter?

Nej nu måste du tänka efter lite. Vi vet att vår string börjar antal bytes efter stdin start. Vi räknar antalet bytes vi skall läsa, med vår getc.
Jag har inte sett nåt av getc() alls, du föreslog att man skulle ta reda på
längden (som jag inte anser är en fast siffra) och sen köra fscanf() på stdin.
När vi sedan hittar slutet på stringen vet vi längden som vi skall läsa.
Du vet längden i det tillfället ja. Inte under hela programmets körning.
Hur i sjutton skulle denna längden kunna ändra sig???? Skall programmet ändra några av våra variabler?
stdin är inte en variabel, det är en stream som kan få data mellan det att
du kör getlength och *scanf(). Det är det jag säger. På ett multitaskande
system kan pipe:n matas kontinuerligt, även mellan det att du kontrollerat
längden och att du läser från den. Om du då läser med en funktion som
inte har en längdbegränsning (t.ex *scanf()) så KAN du åka på att få mer
data än du väntat dig.

Det är allt jag säger.
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote: Du vet längden i det tillfället ja. Inte under hela programmets körning.
stdin är inte en variabel, det är en stream som kan få data mellan det att
du kör getlength och *scanf(). Det är det jag säger. På ett multitaskande
system kan pipe:n matas kontinuerligt, även mellan det att du kontrollerat
längden och att du läser från den. Om du då läser med en funktion som
inte har en längdbegränsning (t.ex *scanf()) så KAN du åka på att få mer
data än du väntat dig.
Något såhär hade jag tänkt mig
fgetpos(stdin);
while (isalpha(getc(stdin)))
length++;
fsetpos( stdin);
buffer = malloc(..*length+1);
fscanf(stdin,"%s",buffer);


Detta är min lilla uppfatting:
Det kommer bara finnas en pipe som stoppar saker till vårt stdin. Alla andra program har sin egna lilla pipe. Du verkar ha hängt upp dig på multitaskning, så testa detta: öppna 2 konsol fönster och skriv i det ena. Självklart står det inget i det andra och det är för att IO enheten inte skickar till pipen för andra fönstret. Det skulle dessutom vara slöseri med datorkraft att göra saker i onödan. För att IO enheten skall skicka till pipen så måste alltså programmet vara aktivt och sagt till att den vill ta emot tryckingar och således sätts avbrottet igång. Detta avbrott enablar man med tex getc och scanf mm hos stdio.h. När vårt program kommer till get så skapas pipen och börjar fyllas med tangent tryckingar. När du trycker return eller pipen är full så alstras avbrottet och programmet läser av pipen och stoppar sakerna i stdin och därifrån arbetar programmet med sina scanf mm. Skulle inte scanf hitta ett slut på en string så var bara pipen full och slår därför inte av avbrottet utan pipe efter pipe kan skickas till stdin. Om det alltså inte står i koden ett getc eller dylikt kommer inget skickas till vår pipe. Därför kommer inte innehållet i stdin ändras hur många program som körs.

Precis som du säger är stdin en stream. En fullt buffrad stream som lever så länge som programet lever och det finns en för varje program. En pipe är inte en stream. När tryckingarna skickats via pipen kommer de att placeras i stdin. Vi vet hur mkt vi skall läsa och på vilken position i streamen det ligger.Det går också att köra en freeopen för den som vill det, som istället directar stdin till en egen fil som man arbetar utifrån.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

[quote="gottegrisen"]Något såhär hade jag tänkt mig
fgetpos(stdin);
while (isalpha(getc(stdin)))
length++;
fsetpos( stdin);
buffer = malloc(..*length+1);
fscanf(stdin,"%s",buffer);


Detta är min lilla uppfatting:
Du verkar ha hängt upp dig på multitaskning/quote]
Jo, det verkar vara den verklighet vi lever i.
Prova detta på en unix-lik shell:

Code: Select all

( cat foobsd.iso ; sleep 100 ; cat foobsd2.iso) | ditt-program.exe
och lägg sedan en sleep(103); i ditt-program efter raden "buffer=.." och säg vad
som händer.

Jag säger inte att folk gör så ofta, men vad gäller pipes och/eller sockets
så finns det inga garantier, alltså är det lika bra att han inte använder någon
av *scanf()-funktionerna eftersom det är lätt att uppfinna ett exempel som
får det att bomba. Om han däremot kör read(..) eller getc() vad-f*n-som-helst
som har en inbyggd längdbegränsning i anropet så är allt klart.

Ta det inte personligt men det är just tankesätt "det är väl ingen som häller en ISO
på stdin" som skapar en del av de problem som program idag råkar ut för.
MS trodde säkert att ingen skulle hälla konstig data på rpc-porten och vips
var det tre exploits på kort tid. Samma sak med IIS-exploitarna (nimda)
osv. De kanske inte tog data via stdin, men de tog data från "okänd källa",
vilket stdin givetvis får räknas som. Jag kör ofta på det här viset:

Code: Select all

prompt> ssh -l identitet dator.domän.se "cat /home/jj/viktig-fil.tar.gz" | tar xzf -
dvs att man häller ett tar.gz-arkiv över ssh och skickar output:en till "tar"
som packar upp lokalt allteftersom det kommer. Här är det ju dels en socket
och dels en lokal pipe som avgör i vilken takt datat kommer och vilken storlek
buffertarna har. Men det skulle störa mig grovt om tar-programmet trillade
omkull för att det råkade komma lite data vid "fel" tillfälle.
Att lägga in "sleep(103);" i ditt-program motsvarar precis det man har på
alla multitaskande OS, en icke-garanti för att två rader i mitt C-program
kommer köras utan avbrott mellan dem. Mellan två assembler-instruktioner
kan dagar gå utan att OS:et eller datorn gör "fel". (mer än att vara skittrist)

Om man inte tar med sånt i sina beräkningar så kommer man skriva sämre
program i mitt tycke. Om man däremot _vet_ att X eller Y inte kan inträffa
så är det en annan sak (t.ex om man parsar argv/argc) men jag upplevde
att originalfrågan gick ut på nåt i stil med: "Hur ser jag till att göra på ett
korrekt sätt och inte bara gissa nåt tal och bli blåst om det skiter sig".

Det är därför som jag fortsätter, inte för argumentationens skull.
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote:

Code: Select all

( cat foobsd.iso ; sleep 100 ; cat foobsd2.iso) | ditt-program.exe
och lägg sedan en sleep(103); i ditt-program efter raden "buffer=.." och säg vad
som händer.
Jo du, den dagen du hittar en iso som bara består av bokstäver skulle vi kanske kunna testa det :) Men om du hade fixat fram det som bara bokstäver, så skulle du märkt att det fungerat. Om du analyserat ditt exempel nogrannt, så skulle du förstått att det är exakt samma sak som att skriva en hemsk mängd bokstäver på konsollen extremt snabt, sedan vänta i 2 sekunder och sedan fortsätta. Det fungerar alldeles utmärkt. Mitt program kommer fortsätta att räkna upp längden tills den hittar ett tecken som markerar ett stringslut.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote:Jo du, den dagen du hittar en iso som bara består av bokstäver skulle vi kanske kunna testa det :)
Det intressanta är inte om en ISO kan innehålla bara bokstäver eller inte,
utan om stdin gör det, och huruvida den kan få mer data mellan din getpos
och din *scanf().

Code: Select all

(cat foobsd.iso ; sleep 102 ; cat foobsd2.iso) | uuencode tempnamn | mitt-program.exe
Så. Där har du enbart 7bitars ascii. Och kom inte och påstå att ingen har
uuenkodat/base64:at stora filer. Internet är fullt av dem... ;-)
Tänk "virusscanner som tar in email (mime = base64) via stdin" om du har
svårt att själv se realistiska exempel från mina kommandorader.
Men om du hade fixat fram det som bara bokstäver, så skulle du märkt att det fungerat. Om du analyserat ditt exempel nogrannt, så skulle du förstått att det är exakt samma sak som att skriva en hemsk mängd bokstäver på konsollen extremt snabt, sedan vänta i 2 sekunder och sedan fortsätta. Det fungerar alldeles utmärkt. Mitt program kommer fortsätta att räkna upp längden tills den hittar ett tecken som markerar ett stringslut.
Hmm. Varför får detta program problem? Jag vägrar acceptera ett svar av
typen "inga ISO's innehåller ü".

Code: Select all

#include "stdio.h"
int main() {
  int i=0;
  char foo[]="fooübar";
  char bar[100];
  for (i=0; i < strlen(foo); i++) {
    printf("isalpha: %c %d\n", foo[i], isalpha((int) foo[i]));
  }
  sscanf(foo, "%s", &bar);
  printf("String would be: %s with len: %d\n", bar, strlen(bar));

  return 0;
}
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
User avatar
gottegrisen
Posts: 221
Joined: 2002-03-11 12:47:17
Location: Mölnlycke

Post by gottegrisen »

IcePic wrote:
gottegrisen wrote:Jo du, den dagen du hittar en iso som bara består av bokstäver skulle vi kanske kunna testa det :)
Det intressanta är inte om en ISO kan innehålla bara bokstäver eller inte,
utan om stdin gör det, och huruvida den kan få mer data mellan din getpos
och din *scanf().

Code: Select all

(cat foobsd.iso ; sleep 102 ; cat foobsd2.iso) | uuencode tempnamn | mitt-program.exe
Så. Där har du enbart 7bitars ascii. Och kom inte och påstå att ingen har
uuenkodat/base64:at stora filer. Internet är fullt av dem... ;-)
Tänk "virusscanner som tar in email (mime = base64) via stdin" om du har
svårt att själv se realistiska exempel från mina kommandorader.
Men om du hade fixat fram det som bara bokstäver, så skulle du märkt att det fungerat. Om du analyserat ditt exempel nogrannt, så skulle du förstått att det är exakt samma sak som att skriva en hemsk mängd bokstäver på konsollen extremt snabt, sedan vänta i 2 sekunder och sedan fortsätta. Det fungerar alldeles utmärkt. Mitt program kommer fortsätta att räkna upp längden tills den hittar ett tecken som markerar ett stringslut.
Hmm. Varför får detta program problem? Jag vägrar acceptera ett svar av
typen "inga ISO's innehåller ü".

Code: Select all

#include "stdio.h"
int main() {
  int i=0;
  char foo[]="fooübar";
  char bar[100];
  for (i=0; i < strlen(foo); i++) {
    printf("isalpha: %c %d\n", foo[i], isalpha((int) foo[i]));
  }
  sscanf(foo, "%s", &bar);
  printf("String would be: %s with len: %d\n", bar, strlen(bar));

  return 0;
}
isalpha är inget bra där, det blev fel i hastigheten. Om vi skall ha "%s" i scanf så måste den självklart ha samma premisser som detta. EOS är nog bättre.

Jag har försökt förklara för dig tidigare.
Jag skall göra det igen på ett snabbt sätt för sista gången. När man trycker i konsollen kommer det åka in i pipen detta sker i FIFO(first in first out) när sedan programmet har läser av pipen hamnar det i stdin. Innan man börjar läsa av så kollar man således positionen på stdin och sedan kontrollerar man hur många tecken man läst in. Dessa vet man att de är i stdin. Den avlästa positionen på stdin är fix, den kommer inte ändras. De antalet tecken vi vill läsa, är efter getc loopen är klar är också fixt. Inget annat program ändrar stdin, då den tillhör vårt program. Så vad har vi:
1 stream
1 pos
1 längd
Där inget annat program kan ändra värderna än vårt. Ganska uppenbart att det kommer fungera.

Det är ju inte konstigare än så. Så om du har problem med förståelsen för pipes, multitasking och avbrott i detta fall, försök inte blanda in dem. Se bara indatan som en lång rad där vi stoppar dem i stdin ett för ett och räknar upp längden. När vi sedan vet längden är det bara till att allockera minnet och läsa från rätt position.

Anledningen till att jag också vet att algoritmen fungerar är:

1) Den följer för mig alla logiska concept jag vet om parallellprogrammering samt processer.

2) Det var en nybörjarlab i C programmering hos chalmers när jag gick där.
User avatar
IcePic
Hedersbit
Posts: 6061
Joined: 2002-03-08 16:09:38

Post by IcePic »

gottegrisen wrote: Jag har försökt förklara för dig tidigare.
Jag skall göra det igen på ett snabbt sätt för sista gången. När man trycker i konsollen kommer det åka in i pipen detta sker i FIFO(first in first out) när sedan programmet har läser av pipen hamnar det i stdin. Innan man börjar läsa av så kollar man således positionen på stdin och sedan kontrollerar man hur många tecken man läst in. Dessa vet man att de är i stdin. Den avlästa positionen på stdin är fix, den kommer inte ändras. De antalet tecken vi vill läsa, är efter getc loopen är klar är också fixt. Inget annat program ändrar stdin, då den tillhör vårt program. Så vad har vi:
1 stream
1 pos
1 längd
Där inget annat program kan ändra värderna än vårt. Ganska uppenbart att det kommer fungera.
Du påstår alltså att inget program kan mata in data i stream:en stdin efter
att du läst av längden på den? Ja eller nej räcker.
Vid "nej", motivera vad som händer i (cat iso; sleep 100; cat iso)|mitt-program-
fallet med streamen stdin efter 100 sekunder. Jag påstår att den ändrar
sig.
Det är ju inte konstigare än så. Så om du har problem med förståelsen för pipes, multitasking och avbrott i detta fall, försök inte blanda in dem. Se bara indatan som en lång rad där vi stoppar dem i stdin ett för ett och räknar upp längden. När vi sedan vet längden är det bara till att allockera minnet och läsa från rätt position.

Anledningen till att jag också vet att algoritmen fungerar är:

1) Den följer för mig alla logiska concept jag vet om parallellprogrammering samt processer.

2) Det var en nybörjarlab i C programmering hos chalmers när jag gick där.
Jag säger inte att din längdberäkning inte stämmer i sig, jag säger att den
inte stämmer när du senare använder den längden som om stdin inte kan
ändra sig.
Gör gärna ett test med ditt-program och lägg en sleep(100) före *scanf()en
för att öka på "window of opportunity":n. (Det är ju bara akademiskt om
man har en stor eller liten chans att det bombar, jag säger att den kan, du
att den inte kan..)
Oh give me a clone, my very own clone,
with the Y chromosome changed to X!
And since she's my own, of my own flesh and bone,
she'll be thinking of nothing but sex!
Post Reply